From f2836979b2c541bfc45b59d9a975cfc32a7afccb Mon Sep 17 00:00:00 2001 From: Grigory Avdyushin Date: Wed, 5 Aug 2020 11:19:14 +0200 Subject: [PATCH 01/32] Update FirebaseCore.def --- firebase-app/src/iosMain/c_interop/FirebaseCore.def | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/firebase-app/src/iosMain/c_interop/FirebaseCore.def b/firebase-app/src/iosMain/c_interop/FirebaseCore.def index f88006b16..cbdfef176 100644 --- a/firebase-app/src/iosMain/c_interop/FirebaseCore.def +++ b/firebase-app/src/iosMain/c_interop/FirebaseCore.def @@ -1,4 +1,4 @@ language = Objective-C modules = FirebaseCore compilerOpts = -framework FirebaseCore -linkerOpts = -framework FirebaseCore -framework FIRAnalyticsConnector -framework FirebaseAnalytics -framework FirebaseCore -framework FirebaseCoreDiagnostics -framework FirebaseInstallations -framework FirebaseInstanceID -framework GoogleAppMeasurement -framework GoogleDataTransport -framework GoogleDataTransportCCTSupport -framework GoogleUtilities -framework PromisesObjC -framework nanopb -framework StoreKit -lsqlite3 \ No newline at end of file +linkerOpts = -framework FirebaseCore -framework abseil -framework gRPC-Core -framework gRPC-C++ -framework BoringSSL-GRPC -framework leveldb-library -framework GoogleUtilities -framework SystemConfiguration -framework FIRAnalyticsConnector -framework FirebaseAnalytics -framework FirebaseCore -framework FirebaseCoreDiagnostics -framework FirebaseInstallations -framework FirebaseInstanceID -framework GoogleAppMeasurement -framework GoogleDataTransport -framework GoogleUtilities -framework PromisesObjC -framework nanopb -framework StoreKit -lsqlite3 From 381f2f761784ed021beda65502f74e2f66430f10 Mon Sep 17 00:00:00 2001 From: Gijs van Veen Date: Mon, 10 Aug 2020 16:40:51 +0200 Subject: [PATCH 02/32] Adding missing Auth calls --- build.gradle.kts | 28 +-- firebase-app/build.gradle.kts | 2 +- firebase-auth/build.gradle.kts | 2 +- .../kotlin/dev/gitlive/firebase/auth/auth.kt | 214 ++++++++++++++++-- .../kotlin/dev/gitlive/firebase/auth/auth.kt | 144 +++++++++++- .../kotlin/dev/gitlive/firebase/auth/auth.kt | 2 + .../kotlin/dev/gitlive/firebase/auth/auth.kt | 2 + firebase-common/build.gradle.kts | 2 +- .../kotlin/dev/gitlive/firebase/externals.kt | 1 + firebase-database/build.gradle.kts | 2 +- firebase-firestore/build.gradle.kts | 2 +- firebase-functions/build.gradle.kts | 2 +- gradle/wrapper/gradle-wrapper.properties | 2 +- 13 files changed, 357 insertions(+), 48 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 2009426dc..cfdf6241d 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -19,7 +19,7 @@ buildscript { } } dependencies { - classpath("com.android.tools.build:gradle:3.6.1") + classpath("com.android.tools.build:gradle:4.0.1") classpath("de.undercouch:gradle-download-task:4.0.4") classpath("com.adarshr:gradle-test-logger-plugin:2.0.0") } @@ -31,8 +31,8 @@ val minSdkVersion by extra(16) tasks { val downloadIOSFirebaseZipFile by creating(Download::class) { - src("https://github.com/firebase/firebase-ios-sdk/releases/download/6.17.0/Firebase-6.17.0.zip") - dest(File(buildDir, "Firebase-6.17.0.zip")) + src("https://github.com/firebase/firebase-ios-sdk/releases/download/6.29.0/Firebase-6.29.0.zip") + dest(File(buildDir, "Firebase-6.29.0.zip")) if (System.getenv("token") != null) { username(System.getenv("token")) } @@ -41,7 +41,7 @@ tasks { val unzipIOSFirebase by creating(Copy::class) { if (!File("$buildDir/Firebase").exists()) { - val zipFile = File(buildDir, "Firebase-6.17.0.zip") + val zipFile = File(buildDir, "Firebase-6.29.0.zip") if (!zipFile.exists()) { dependsOn(downloadIOSFirebaseZipFile) } @@ -172,24 +172,24 @@ subprojects { dependencies { "commonMainImplementation"(kotlin("stdlib-common")) - "commonMainImplementation"("org.jetbrains.kotlinx:kotlinx-coroutines-core-common:1.3.6") + "commonMainImplementation"("org.jetbrains.kotlinx:kotlinx-coroutines-core-common:1.3.8") "jsMainImplementation"(kotlin("stdlib-js")) - "jsMainImplementation"("org.jetbrains.kotlinx:kotlinx-coroutines-core-js:1.3.6") - "androidMainImplementation"("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.6") + "jsMainImplementation"("org.jetbrains.kotlinx:kotlinx-coroutines-core-js:1.3.8") + "androidMainImplementation"("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.8") "androidMainImplementation"("org.jetbrains.kotlinx:kotlinx-coroutines-play-services:1.3.6") - "iosMainImplementation"("org.jetbrains.kotlinx:kotlinx-coroutines-core-common:1.3.6") - "iosMainImplementation"("org.jetbrains.kotlinx:kotlinx-coroutines-core-native:1.3.6") + "iosMainImplementation"("org.jetbrains.kotlinx:kotlinx-coroutines-core-common:1.3.8") + "iosMainImplementation"("org.jetbrains.kotlinx:kotlinx-coroutines-core-native:1.3.8") "commonTestImplementation"(kotlin("test-common")) "commonTestImplementation"(kotlin("test-annotations-common")) - "commonTestImplementation"("org.jetbrains.kotlinx:kotlinx-coroutines-core-common:1.3.6") - "commonTestImplementation"("org.jetbrains.kotlinx:kotlinx-coroutines-test:1.3.6") + "commonTestImplementation"("org.jetbrains.kotlinx:kotlinx-coroutines-core-common:1.3.8") + "commonTestImplementation"("org.jetbrains.kotlinx:kotlinx-coroutines-test:1.3.8") "jsTestImplementation"(kotlin("test-js")) "androidAndroidTestImplementation"(kotlin("test-junit")) - "androidAndroidTestImplementation"("junit:junit:4.12") + "androidAndroidTestImplementation"("junit:junit:4.13") "androidAndroidTestImplementation"("androidx.test:core:1.2.0") - "androidAndroidTestImplementation"("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.6") + "androidAndroidTestImplementation"("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.8") "androidAndroidTestImplementation"("androidx.test.ext:junit:1.1.1") - "androidAndroidTestImplementation"("androidx.test:runner:1.1.0") + "androidAndroidTestImplementation"("androidx.test:runner:1.2.0") } } diff --git a/firebase-app/build.gradle.kts b/firebase-app/build.gradle.kts index 5c052146b..91486b2c9 100644 --- a/firebase-app/build.gradle.kts +++ b/firebase-app/build.gradle.kts @@ -87,7 +87,7 @@ kotlin { } val androidMain by getting { dependencies { - api("com.google.firebase:firebase-common:19.2.0") + api("com.google.firebase:firebase-common:19.3.0") } } diff --git a/firebase-auth/build.gradle.kts b/firebase-auth/build.gradle.kts index 9a2bd8a82..32e591fce 100644 --- a/firebase-auth/build.gradle.kts +++ b/firebase-auth/build.gradle.kts @@ -103,7 +103,7 @@ kotlin { val androidMain by getting { dependencies { - api("com.google.firebase:firebase-auth:19.1.0") + api("com.google.firebase:firebase-auth:19.3.0") } } 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 04023550f..64f072a85 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 @@ -4,11 +4,15 @@ package dev.gitlive.firebase.auth +import android.net.Uri +import com.google.firebase.auth.ActionCodeEmailInfo +import com.google.firebase.auth.ActionCodeMultiFactorInfo import com.google.firebase.auth.EmailAuthProvider import com.google.firebase.auth.FirebaseAuth.AuthStateListener import dev.gitlive.firebase.Firebase import dev.gitlive.firebase.FirebaseApp import kotlinx.coroutines.channels.awaitClose +import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.callbackFlow import kotlinx.coroutines.tasks.await @@ -22,43 +26,97 @@ actual class FirebaseAuth internal constructor(val android: com.google.firebase. actual val currentUser: FirebaseUser? get() = android.currentUser?.let { FirebaseUser(it) } - actual suspend fun sendPasswordResetEmail(email: String) { - android.sendPasswordResetEmail(email).await() + actual val authStateChanged get() = callbackFlow { + val listener = AuthStateListener { auth -> offer(auth.currentUser?.let { FirebaseUser(it) }) } + android.addAuthStateListener(listener) + awaitClose { android.removeAuthStateListener(listener) } } - actual suspend fun signInWithEmailAndPassword(email: String, password: String) = - AuthResult(android.signInWithEmailAndPassword(email, password).await()) + actual val idTokenChanged: Flow + get() = callbackFlow { + val listener = com.google.firebase.auth.FirebaseAuth.IdTokenListener { auth -> offer(auth.currentUser?.let { FirebaseUser(it) })} + android.addIdTokenListener(listener) + awaitClose { android.removeIdTokenListener(listener) } + } + + actual var languageCode: String + get() = android.languageCode ?: "" + set(value) { android.setLanguageCode(value) } + + actual suspend fun applyActionCode(code: String) = android.applyActionCode(code).await().run { Unit } + actual suspend fun checkActionCode(code: String): ActionCodeResult = ActionCodeResult(android.checkActionCode(code).await()) + actual suspend fun confirmPasswordReset(code: String, newPassword: String) = android.confirmPasswordReset(code, newPassword).await().run { Unit } actual suspend fun createUserWithEmailAndPassword(email: String, password: String) = AuthResult(android.createUserWithEmailAndPassword(email, password).await()) + actual suspend fun fetchSignInMethodsForEmail(email: String): SignInMethodQueryResult = SignInMethodQueryResult(android.fetchSignInMethodsForEmail(email).await()) + + actual suspend fun sendPasswordResetEmail(email: String, actionCodeSettings: ActionCodeSettings?) { + android.sendPasswordResetEmail(email, actionCodeSettings?.android).await() + } + + actual suspend fun sendSignInLinkToEmail(email: String, actionCodeSettings: ActionCodeSettings) = android.sendSignInLinkToEmail(email, actionCodeSettings.android).await().run { Unit } + + actual suspend fun signInWithEmailAndPassword(email: String, password: String) = + AuthResult(android.signInWithEmailAndPassword(email, password).await()) + actual suspend fun signInWithCustomToken(token: String) = AuthResult(android.signInWithCustomToken(token).await()) actual suspend fun signInAnonymously() = AuthResult(android.signInAnonymously().await()) - actual val authStateChanged get() = callbackFlow { - val listener = object : AuthStateListener { - override fun onAuthStateChanged(auth: com.google.firebase.auth.FirebaseAuth) { - offer(auth.currentUser?.let { FirebaseUser(it) }) - } - } - android.addAuthStateListener(listener) - awaitClose { android.removeAuthStateListener(listener) } - } actual suspend fun signInWithCredential(authCredential: AuthCredential) = AuthResult(android.signInWithCredential(authCredential.android).await()) actual suspend fun signOut() = android.signOut() + + actual suspend fun updateCurrentUser(user: FirebaseUser) = android.updateCurrentUser(user.android).await().run { Unit } + actual suspend fun verifyPasswordResetCode(code: String): String = android.verifyPasswordResetCode(code).await() } -actual class AuthCredential(val android: com.google.firebase.auth.AuthCredential) +actual open class AuthCredential(open val android: com.google.firebase.auth.AuthCredential) { + actual val providerId: String + get() = android.provider + actual val signInMethod: String + get() = android.signInMethod +} + +actual class PhoneAuthCredential(override val android: com.google.firebase.auth.PhoneAuthCredential) : AuthCredential(android) { + actual val smsCode: String? + get() = android.smsCode +} actual class AuthResult internal constructor(val android: com.google.firebase.auth.AuthResult) { actual val user: FirebaseUser? get() = android.user?.let { FirebaseUser(it) } } +actual class ActionCodeResult(val android: com.google.firebase.auth.ActionCodeResult) { + actual val operation: Operation + get() = when (android.operation) { + com.google.firebase.auth.ActionCodeResult.PASSWORD_RESET -> Operation.PasswordReset + com.google.firebase.auth.ActionCodeResult.VERIFY_EMAIL -> Operation.VerifyEmail + com.google.firebase.auth.ActionCodeResult.RECOVER_EMAIL -> Operation.RecoverEmail + com.google.firebase.auth.ActionCodeResult.ERROR -> Operation.Error + com.google.firebase.auth.ActionCodeResult.SIGN_IN_WITH_EMAIL_LINK -> Operation.SignInWithEmailLink + com.google.firebase.auth.ActionCodeResult.VERIFY_BEFORE_CHANGE_EMAIL -> Operation.VerifyBeforeChangeEmail + com.google.firebase.auth.ActionCodeResult.REVERT_SECOND_FACTOR_ADDITION -> Operation.RevertSecondFactorAddition + else -> Operation.Error + } + actual fun > getData(type: A): T? = when (type) { + is ActionCodeDataType.Email -> android.info?.email + is ActionCodeDataType.PreviousEmail -> (android.info as? ActionCodeEmailInfo)?.previousEmail + is ActionCodeDataType.MultiFactor -> (android.info as? ActionCodeMultiFactorInfo)?.multiFactorInfo?.let { MultiFactorInfo(it) } + else -> null + } as? T +} + +actual class SignInMethodQueryResult(val android: com.google.firebase.auth.SignInMethodQueryResult) { + actual val signInMethods: List + get() = android.signInMethods ?: emptyList() +} + actual class FirebaseUser internal constructor(val android: com.google.firebase.auth.FirebaseUser) { actual val uid: String get() = android.uid @@ -68,11 +126,74 @@ actual class FirebaseUser internal constructor(val android: com.google.firebase. get() = android.email actual val phoneNumber: String? get() = android.phoneNumber + actual val photoURL: String? + get() = android.photoUrl?.toString() actual val isAnonymous: Boolean get() = android.isAnonymous + actual val isEmailVerified: Boolean + get() = android.isEmailVerified + actual val metaData: MetaData? + get() = android.metadata?.let{ MetaData(it) } + actual val multiFactor: MultiFactor + get() = MultiFactor(android.multiFactor) + actual val providerData: List + get() = android.providerData.map { UserInfo(it) } + actual val providerId: String + get() = android.providerId actual suspend fun delete() = android.delete().await().run { Unit } actual suspend fun reload() = android.reload().await().run { Unit } - actual suspend fun sendEmailVerification() = android.sendEmailVerification().await().run { Unit } + actual suspend fun getIdToken(forceRefresh: Boolean) = android.getIdToken(forceRefresh).await().run { Unit } + actual suspend fun linkWithCredential(credential: AuthCredential): AuthResult = AuthResult(android.linkWithCredential(credential.android).await()) + actual suspend fun reauthenticate(credential: AuthCredential) = android.reauthenticate(credential.android).await().run { Unit } + actual suspend fun reauthenticateAndRetrieveData(credential: AuthCredential): AuthResult = AuthResult(android.reauthenticateAndRetrieveData(credential.android).await()) + actual suspend fun sendEmailVerification(actionCodeSettings: ActionCodeSettings?) { + val request = actionCodeSettings?.android?.let { android.sendEmailVerification(it) } ?: android.sendEmailVerification() + request.await().run { Unit } + } + actual suspend fun unlink(provider: String): AuthResult = AuthResult(android.unlink(provider).await()) + actual suspend fun updateEmail(email: String) = android.updateEmail(email).await().run { Unit } + actual suspend fun updatePassword(password: String) = android.updatePassword(password).await().run { Unit } + actual suspend fun updatePhoneNumber(credential: PhoneAuthCredential) = android.updatePhoneNumber(credential.android).await().run { Unit } + actual suspend fun updateProfile(request: UserProfileChangeRequest) = android.updateProfile(request.android).await().run { Unit } + actual suspend fun verifyBeforeUpdateEmail(newEmail: String, actionCodeSettings: ActionCodeSettings?) = android.verifyBeforeUpdateEmail(newEmail, actionCodeSettings?.android).await().run { Unit } +} + +actual class UserInfo(val android: com.google.firebase.auth.UserInfo) { + actual val displayName: String? + get() = android.displayName + actual val email: String? + get() = android.email + actual val phoneNumber: String? + get() = android.phoneNumber + actual val photoURL: String? + get() = android.photoUrl?.toString() + actual val providerId: String + get() = android.providerId + actual val uid: String + get() = android.uid +} + +actual class MetaData(val android: com.google.firebase.auth.FirebaseUserMetadata) { + actual val creationTime: Long? + get() = android.creationTimestamp + actual val lastSignInTime: Long? + get() = android.lastSignInTimestamp +} + +actual class UserProfileChangeRequest(val android: com.google.firebase.auth.UserProfileChangeRequest) { + actual class Builder(val android: com.google.firebase.auth.UserProfileChangeRequest.Builder = com.google.firebase.auth.UserProfileChangeRequest.Builder()) { + actual fun setDisplayName(displayName: String?): Builder = apply { + android.setDisplayName(displayName) + } + actual fun setPhotoURL(photoURL: String?): Builder = apply { + android.setPhotoUri(photoURL?.let { Uri.parse(it) }) + } + actual fun build(): UserProfileChangeRequest = UserProfileChangeRequest(android.build()) + } + actual val displayName: String? + get() = android.displayName + actual val photoURL: String? + get() = android.photoUri?.toString() } actual typealias FirebaseAuthException = com.google.firebase.auth.FirebaseAuthException @@ -80,8 +201,10 @@ actual typealias FirebaseAuthActionCodeException = com.google.firebase.auth.Fire actual typealias FirebaseAuthEmailException = com.google.firebase.auth.FirebaseAuthEmailException actual typealias FirebaseAuthInvalidCredentialsException = com.google.firebase.auth.FirebaseAuthInvalidCredentialsException actual typealias FirebaseAuthInvalidUserException = com.google.firebase.auth.FirebaseAuthInvalidUserException +actual typealias FirebaseAuthMultiFactorException = com.google.firebase.auth.FirebaseAuthMultiFactorException actual typealias FirebaseAuthRecentLoginRequiredException = com.google.firebase.auth.FirebaseAuthRecentLoginRequiredException actual typealias FirebaseAuthUserCollisionException = com.google.firebase.auth.FirebaseAuthUserCollisionException +actual typealias FirebaseAuthWeakPasswordException = com.google.firebase.auth.FirebaseAuthWeakPasswordException actual typealias FirebaseAuthWebException = com.google.firebase.auth.FirebaseAuthWebException actual object EmailAuthProvider { @@ -89,4 +212,65 @@ actual object EmailAuthProvider { email: String, password: String ): AuthCredential = AuthCredential(EmailAuthProvider.getCredential(email, password)) +} + +actual class MultiFactor(val android: com.google.firebase.auth.MultiFactor) { + actual val enrolledFactors: List + get() = android.enrolledFactors.map { MultiFactorInfo(it) } + actual suspend fun enroll(multiFactorAssertion: MultiFactorAssertion, displayName: String?) = android.enroll(multiFactorAssertion.android, displayName).await().run { Unit } + actual suspend fun getSession(): MultiFactorSession = MultiFactorSession(android.session.await()) + actual suspend fun unenroll(multiFactorInfo: MultiFactorInfo) = android.unenroll(multiFactorInfo.android).await().run { Unit } + actual suspend fun unenroll(factorUid: String) = android.unenroll(factorUid).await().run { Unit } +} + +actual class MultiFactorInfo(val android: com.google.firebase.auth.MultiFactorInfo) { + actual val displayName: String? + get() = android.displayName + actual val enrollmentTime: Long + get() = android.enrollmentTimestamp + actual val factorId: String + get() = android.factorId + actual val uid: String + get() = android.uid +} + +actual class MultiFactorAssertion(val android: com.google.firebase.auth.MultiFactorAssertion) { + actual val factorId: String + get() = android.factorId +} + +actual class MultiFactorSession(val android: com.google.firebase.auth.MultiFactorSession) + +actual class ActionCodeSettings private constructor(val android: com.google.firebase.auth.ActionCodeSettings) { + actual class Builder(val android: com.google.firebase.auth.ActionCodeSettings.Builder = com.google.firebase.auth.ActionCodeSettings.newBuilder()) { + actual fun setAndroidPackageName(androidPackageName: String, installIfNotAvailable: Boolean, minimumVersion: String?): Builder = apply { + android.setAndroidPackageName(androidPackageName, installIfNotAvailable, minimumVersion) + } + actual fun setDynamicLinkDomain(dynamicLinkDomain: String): Builder = apply { + android.setDynamicLinkDomain(dynamicLinkDomain) + } + actual fun setHandleCodeInApp(status: Boolean): Builder = apply { + android.setHandleCodeInApp(status) + } + actual fun setIOSBundleId(iOSBundleId: String): Builder = apply { + android.setIOSBundleId(iOSBundleId) + } + actual fun setUrl(url: String): Builder = apply { + android.setUrl(url) + } + actual fun build(): ActionCodeSettings = ActionCodeSettings(android.build()) + } + + actual val canHandleCodeInApp: Boolean + get() = android.canHandleCodeInApp() + actual val androidInstallApp: Boolean + get() = android.androidInstallApp + actual val androidMinimumVersion: String? + get() = android.androidMinimumVersion + actual val androidPackageName: String? + get() = android.androidPackageName + actual val iOSBundle: String? + get() = android.iosBundle + actual val url: String + get() = android.url } \ No newline at end of file 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 067f2ecb1..9f71c200e 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 @@ -18,28 +18,51 @@ expect fun Firebase.auth(app: FirebaseApp): FirebaseAuth expect class FirebaseAuth { val currentUser: FirebaseUser? val authStateChanged: Flow - suspend fun sendPasswordResetEmail(email: String) - suspend fun signInWithEmailAndPassword(email: String, password: String): AuthResult + val idTokenChanged: Flow + var languageCode: String + suspend fun applyActionCode(code: String) + suspend fun checkActionCode(code: String): ActionCodeResult + suspend fun confirmPasswordReset(code: String, newPassword: String) suspend fun createUserWithEmailAndPassword(email: String, password: String): AuthResult + suspend fun fetchSignInMethodsForEmail(email: String): SignInMethodQueryResult + suspend fun sendPasswordResetEmail(email: String, actionCodeSettings: ActionCodeSettings? = null) + suspend fun sendSignInLinkToEmail(email: String, actionCodeSettings: ActionCodeSettings) + suspend fun signInWithEmailAndPassword(email: String, password: String): AuthResult suspend fun signInWithCustomToken(token: String): AuthResult suspend fun signInAnonymously(): AuthResult suspend fun signInWithCredential(authCredential: AuthCredential): AuthResult suspend fun signOut() + suspend fun updateCurrentUser(user: FirebaseUser) + suspend fun verifyPasswordResetCode(code: String): String } expect class AuthResult { val user: FirebaseUser? } -expect class FirebaseUser { - val uid: String - val displayName: String? - val email: String? - val phoneNumber: String? - val isAnonymous: Boolean - suspend fun delete() - suspend fun reload() - suspend fun sendEmailVerification() +expect class ActionCodeResult { + val operation: Operation + fun > getData(type: A): T? +} + +expect class SignInMethodQueryResult { + val signInMethods: List +} + +enum class Operation { + PasswordReset, + VerifyEmail, + RecoverEmail, + Error, + SignInWithEmailLink, + VerifyBeforeChangeEmail, + RevertSecondFactorAddition +} + +sealed class ActionCodeDataType { + object Email : ActionCodeDataType() + object PreviousEmail : ActionCodeDataType() + object MultiFactor : ActionCodeDataType() } expect open class FirebaseAuthException : FirebaseException @@ -47,13 +70,110 @@ expect class FirebaseAuthActionCodeException : FirebaseAuthException expect class FirebaseAuthEmailException : FirebaseAuthException expect class FirebaseAuthInvalidCredentialsException : FirebaseAuthException expect class FirebaseAuthInvalidUserException : FirebaseAuthException +expect class FirebaseAuthMultiFactorException: FirebaseAuthException expect class FirebaseAuthRecentLoginRequiredException : FirebaseAuthException expect class FirebaseAuthUserCollisionException : FirebaseAuthException +expect class FirebaseAuthWeakPasswordException : FirebaseAuthException expect class FirebaseAuthWebException : FirebaseAuthException -expect class AuthCredential +expect open class AuthCredential { + val providerId: String + val signInMethod: String +} +expect class PhoneAuthCredential : AuthCredential { + val smsCode: String? +} expect object EmailAuthProvider{ fun credentialWithEmail(email: String, password: String): AuthCredential } +expect class FirebaseUser { + val uid: String + val displayName: String? + val email: String? + val phoneNumber: String? + val photoURL: String? + val isAnonymous: Boolean + val isEmailVerified: Boolean + val metaData: MetaData? + val multiFactor: MultiFactor + val providerData: List + val providerId: String + suspend fun delete() + suspend fun reload() + suspend fun getIdToken(forceRefresh: Boolean) + suspend fun linkWithCredential(credential: AuthCredential): AuthResult + suspend fun reauthenticate(credential: AuthCredential) + suspend fun reauthenticateAndRetrieveData(credential: AuthCredential): AuthResult + suspend fun sendEmailVerification(actionCodeSettings: ActionCodeSettings? = null) + suspend fun unlink(provider: String): AuthResult + suspend fun updateEmail(email: String) + suspend fun updatePassword(password: String) + suspend fun updatePhoneNumber(credential: PhoneAuthCredential) + suspend fun updateProfile(request: UserProfileChangeRequest) + suspend fun verifyBeforeUpdateEmail(newEmail: String, actionCodeSettings: ActionCodeSettings? = null) +} + +expect class UserInfo { + val displayName: String? + val email: String? + val phoneNumber: String? + val photoURL: String? + val providerId: String + val uid: String +} + +expect class MetaData { + val creationTime: Long? + val lastSignInTime: Long? +} + +expect class UserProfileChangeRequest { + class Builder { + fun setDisplayName(displayName: String?): Builder + fun setPhotoURL(photoURL: String?): Builder + fun build(): UserProfileChangeRequest + } + val displayName: String? + val photoURL: String? +} + +expect class MultiFactor { + val enrolledFactors: List + suspend fun enroll(multiFactorAssertion: MultiFactorAssertion, displayName: String?) + suspend fun getSession(): MultiFactorSession + suspend fun unenroll(multiFactorInfo: MultiFactorInfo) + suspend fun unenroll(factorUid: String) +} + +expect class MultiFactorInfo { + val displayName: String? + val enrollmentTime: Long + val factorId: String + val uid: String +} + +expect class MultiFactorAssertion { + val factorId: String +} + +expect class MultiFactorSession + +expect class ActionCodeSettings { + class Builder { + fun setAndroidPackageName(androidPackageName: String, installIfNotAvailable: Boolean, minimumVersion: String?): Builder + fun setDynamicLinkDomain(dynamicLinkDomain: String): Builder + fun setHandleCodeInApp(status: Boolean): Builder + fun setIOSBundleId(iOSBundleId: String): Builder + fun setUrl(url: String): Builder + fun build(): ActionCodeSettings + } + + val canHandleCodeInApp: Boolean + val androidInstallApp: Boolean + val androidMinimumVersion: String? + val androidPackageName: String? + val iOSBundle: String? + val url: String +} 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 f85e3c8e6..7317a1e89 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 @@ -69,6 +69,8 @@ actual class FirebaseUser internal constructor(val ios: FIRUser) { get() = ios.phoneNumber actual val isAnonymous: Boolean get() = ios.isAnonymous() + actual val isEmailVerified: Boolean + get() = ios.emailVerified actual suspend fun delete() = ios.await { deleteWithCompletion(it) }.run { Unit } actual suspend fun reload() = ios.await { reloadWithCompletion(it) }.run { Unit } actual suspend fun sendEmailVerification() = ios.await { sendEmailVerificationWithCompletion(it) }.run { Unit } 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 30f9f6956..1164568ac 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 @@ -66,6 +66,8 @@ actual class FirebaseUser internal constructor(val js: firebase.user.User) { get() = rethrow { js.phoneNumber } actual val isAnonymous: Boolean get() = rethrow { js.isAnonymous } + actual val isEmailVerified: Boolean + get() = dev.gitlive.firebase.auth.rethrow { js.emailVerified } actual suspend fun delete() = rethrow { js.delete().await() } actual suspend fun reload() = rethrow { js.reload().await() } actual suspend fun sendEmailVerification() = rethrow { js.sendEmailVerification().await() } diff --git a/firebase-common/build.gradle.kts b/firebase-common/build.gradle.kts index edc3c5a8a..e4116af67 100644 --- a/firebase-common/build.gradle.kts +++ b/firebase-common/build.gradle.kts @@ -69,7 +69,7 @@ kotlin { } val androidMain by getting { dependencies { - api("com.google.firebase:firebase-common:19.2.0") + api("com.google.firebase:firebase-common:19.3.0") api("org.jetbrains.kotlinx:kotlinx-serialization-runtime:0.20.0") } } diff --git a/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals.kt b/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals.kt index fe68e1d43..bdb82b459 100644 --- a/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals.kt +++ b/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals.kt @@ -90,6 +90,7 @@ external object firebase { val email: String? val phoneNumber: String? val isAnonymous: Boolean + val emailVerified: Boolean fun delete(): Promise fun reload(): Promise diff --git a/firebase-database/build.gradle.kts b/firebase-database/build.gradle.kts index 09c4a588b..0454cf4c3 100644 --- a/firebase-database/build.gradle.kts +++ b/firebase-database/build.gradle.kts @@ -71,7 +71,7 @@ kotlin { } val androidMain by getting { dependencies { - api("com.google.firebase:firebase-database:17.0.0") + api("com.google.firebase:firebase-database:19.3.0") } } val jsMain by getting {} diff --git a/firebase-firestore/build.gradle.kts b/firebase-firestore/build.gradle.kts index 949057197..4db6c1efa 100644 --- a/firebase-firestore/build.gradle.kts +++ b/firebase-firestore/build.gradle.kts @@ -67,7 +67,7 @@ kotlin { } val androidMain by getting { dependencies { - api("com.google.firebase:firebase-firestore:21.4.3") + api("com.google.firebase:firebase-firestore:21.5.0") implementation("com.android.support:multidex:1.0.3") } } diff --git a/firebase-functions/build.gradle.kts b/firebase-functions/build.gradle.kts index 8924bee86..85ddf911d 100644 --- a/firebase-functions/build.gradle.kts +++ b/firebase-functions/build.gradle.kts @@ -65,7 +65,7 @@ kotlin { } val androidMain by getting { dependencies { - api("com.google.firebase:firebase-functions:19.0.1") + api("com.google.firebase:firebase-functions:19.0.2") } } val iosMain by getting {} diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index a23876d58..b62e103ed 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.4-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.5.1-all.zip From f8e08849a59885ad2bdcab69320e2f4bd023d08d Mon Sep 17 00:00:00 2001 From: Gijs van Veen Date: Tue, 11 Aug 2020 14:39:18 +0200 Subject: [PATCH 03/32] Add iOS implementation --- build.gradle.kts | 2 +- firebase-app/build.gradle.kts | 8 +- .../src/iosMain/c_interop/FirebaseCore.def | 2 +- firebase-auth/build.gradle.kts | 14 +- firebase-auth/firebase_auth.podspec | 44 ++++ .../kotlin/dev/gitlive/firebase/auth/auth.kt | 14 +- .../kotlin/dev/gitlive/firebase/auth/auth.kt | 9 +- .../kotlin/dev/gitlive/firebase/auth/auth.kt | 215 +++++++++++++++++- firebase-database/build.gradle.kts | 6 +- firebase-firestore/build.gradle.kts | 4 +- firebase-functions/build.gradle.kts | 4 +- 11 files changed, 285 insertions(+), 37 deletions(-) create mode 100644 firebase-auth/firebase_auth.podspec diff --git a/build.gradle.kts b/build.gradle.kts index cfdf6241d..03cbd6c63 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -31,7 +31,7 @@ val minSdkVersion by extra(16) tasks { val downloadIOSFirebaseZipFile by creating(Download::class) { - src("https://github.com/firebase/firebase-ios-sdk/releases/download/6.29.0/Firebase-6.29.0.zip") + src("https://github.com/firebase/firebase-ios-sdk/releases/download/CocoaPods-6.29.0/Firebase.zip") dest(File(buildDir, "Firebase-6.29.0.zip")) if (System.getenv("token") != null) { username(System.getenv("token")) diff --git a/firebase-app/build.gradle.kts b/firebase-app/build.gradle.kts index 91486b2c9..c90143509 100644 --- a/firebase-app/build.gradle.kts +++ b/firebase-app/build.gradle.kts @@ -67,7 +67,9 @@ kotlin { val iosX64 = iosX64("ios") { binaries { getTest("DEBUG").apply { - linkerOpts("-F${rootProject.buildDir}/Firebase/FirebaseAnalytics") + linkerOpts("-F${rootProject.buildDir}/Firebase/FirebaseAnalytics/FirebaseCore.xcframework/ios-armv7_arm64", + "-F${rootProject.buildDir}/Firebase/FirebaseAnalytics/FirebaseCore.xcframework/ios-i386_x86_64-simulator", + "-F${rootProject.buildDir}/Firebase/FirebaseAnalytics/FirebaseCore.xcframework/ios-x86_64-maccatalyst") linkerOpts("-ObjC") } } @@ -97,7 +99,9 @@ kotlin { val firebasecore by cinterops.creating { packageName("cocoapods.FirebaseCore") defFile(file("$projectDir/src/iosMain/c_interop/FirebaseCore.def")) - compilerOpts("-F${rootProject.buildDir}/Firebase/FirebaseAnalytics") + compilerOpts("-F${rootProject.buildDir}/Firebase/FirebaseAnalytics/FirebaseCore.xcframework/ios-armv7_arm64", + "-F${rootProject.buildDir}/Firebase/FirebaseAnalytics/FirebaseCore.xcframework/ios-i386_x86_64-simulator", + "-F${rootProject.buildDir}/Firebase/FirebaseAnalytics/FirebaseCore.xcframework/ios-x86_64-maccatalyst") } } } diff --git a/firebase-app/src/iosMain/c_interop/FirebaseCore.def b/firebase-app/src/iosMain/c_interop/FirebaseCore.def index f88006b16..d2df640af 100644 --- a/firebase-app/src/iosMain/c_interop/FirebaseCore.def +++ b/firebase-app/src/iosMain/c_interop/FirebaseCore.def @@ -1,4 +1,4 @@ language = Objective-C modules = FirebaseCore compilerOpts = -framework FirebaseCore -linkerOpts = -framework FirebaseCore -framework FIRAnalyticsConnector -framework FirebaseAnalytics -framework FirebaseCore -framework FirebaseCoreDiagnostics -framework FirebaseInstallations -framework FirebaseInstanceID -framework GoogleAppMeasurement -framework GoogleDataTransport -framework GoogleDataTransportCCTSupport -framework GoogleUtilities -framework PromisesObjC -framework nanopb -framework StoreKit -lsqlite3 \ No newline at end of file +linkerOpts = -framework FirebaseCore -framework FIRAnalyticsConnector -framework FirebaseAnalytics -framework FirebaseCore -framework FirebaseCoreDiagnostics -framework FirebaseInstallations -framework FirebaseInstanceID -framework GoogleAppMeasurement -framework GoogleDataTransport -framework GoogleUtilities -framework PromisesObjC -framework nanopb -framework StoreKit -lsqlite3 \ No newline at end of file diff --git a/firebase-auth/build.gradle.kts b/firebase-auth/build.gradle.kts index 32e591fce..c98dc3dcf 100644 --- a/firebase-auth/build.gradle.kts +++ b/firebase-auth/build.gradle.kts @@ -76,8 +76,12 @@ kotlin { val iosX64 = iosX64("ios") { binaries { getTest("DEBUG").apply { - linkerOpts("-F${rootProject.buildDir}/Firebase/FirebaseAnalytics") - linkerOpts("-F${rootProject.buildDir}/Firebase/FirebaseAuth") + linkerOpts("-F${rootProject.buildDir}/Firebase/FirebaseAnalytics/FirebaseCore.xcframework/ios-armv7_arm64", + "-F${rootProject.buildDir}/Firebase/FirebaseAnalytics/FirebaseCore.xcframework/ios-i386_x86_64-simulator", + "-F${rootProject.buildDir}/Firebase/FirebaseAnalytics/FirebaseCore.xcframework/ios-x86_64-maccatalyst") + linkerOpts("-F${rootProject.buildDir}/Firebase/FirebaseAuth/FirebaseAuth.xcframework/ios-armv7_arm64", + "-F${rootProject.buildDir}/Firebase/FirebaseAuth/FirebaseAuth.xcframework/ios-i386_x86_64-simulator", + "-F${rootProject.buildDir}/Firebase/FirebaseAuth/FirebaseAuth.xcframework/ios-x86_64-maccatalyst") linkerOpts("-F${rootProject.buildDir}/Firebase/GoogleSignIn") linkerOpts("-ObjC") // compilerOpts("-framework AppAuth") @@ -103,7 +107,7 @@ kotlin { val androidMain by getting { dependencies { - api("com.google.firebase:firebase-auth:19.3.0") + api("com.google.firebase:firebase-auth:19.3.2") } } @@ -113,7 +117,9 @@ kotlin { val firebaseAuth by cinterops.creating { packageName("cocoapods.FirebaseAuth") defFile(file("$projectDir/src/iosMain/c_interop/FirebaseAuth.def")) - compilerOpts("-F$projectDir/../build/Firebase/FirebaseAuth") + compilerOpts("-F${rootProject.buildDir}/Firebase/FirebaseAuth/FirebaseAuth.xcframework/ios-armv7_arm64", + "-F${rootProject.buildDir}/Firebase/FirebaseAuth/FirebaseAuth.xcframework/ios-i386_x86_64-simulator", + "-F${rootProject.buildDir}/Firebase/FirebaseAuth/FirebaseAuth.xcframework/ios-x86_64-maccatalyst") compilerOpts("-F$projectDir/../build/Firebase/GoogleSignIn") } } diff --git a/firebase-auth/firebase_auth.podspec b/firebase-auth/firebase_auth.podspec new file mode 100644 index 000000000..21ef430a9 --- /dev/null +++ b/firebase-auth/firebase_auth.podspec @@ -0,0 +1,44 @@ +Pod::Spec.new do |spec| + spec.name = 'firebase_auth' + spec.version = '0.2.0' + spec.homepage = '' + spec.source = { :git => "Not Published", :tag => "Cocoapods/#{spec.name}/#{spec.version}" } + spec.authors = '' + spec.license = '' + spec.summary = '' + + spec.static_framework = true + spec.vendored_frameworks = "build/cocoapods/framework/firebase_auth.framework" + spec.libraries = "c++" + spec.module_name = "#{spec.name}_umbrella" + + + + spec.pod_target_xcconfig = { + 'KOTLIN_TARGET[sdk=iphonesimulator*]' => 'ios_x64', + 'KOTLIN_TARGET[sdk=iphoneos*]' => 'ios_arm', + 'KOTLIN_TARGET[sdk=watchsimulator*]' => 'watchos_x86', + 'KOTLIN_TARGET[sdk=watchos*]' => 'watchos_arm', + 'KOTLIN_TARGET[sdk=appletvsimulator*]' => 'tvos_x64', + 'KOTLIN_TARGET[sdk=appletvos*]' => 'tvos_arm64', + 'KOTLIN_TARGET[sdk=macosx*]' => 'macos_x64' + } + + spec.script_phases = [ + { + :name => 'Build firebase_auth', + :execution_position => :before_compile, + :shell_path => '/bin/sh', + :script => <<-SCRIPT + set -ev + REPO_ROOT="$PODS_TARGET_SRCROOT" + "$REPO_ROOT/../gradlew" -p "$REPO_ROOT" :firebase-auth:syncFramework \ + -Pkotlin.native.cocoapods.target=$KOTLIN_TARGET \ + -Pkotlin.native.cocoapods.configuration=$CONFIGURATION \ + -Pkotlin.native.cocoapods.cflags="$OTHER_CFLAGS" \ + -Pkotlin.native.cocoapods.paths.headers="$HEADER_SEARCH_PATHS" \ + -Pkotlin.native.cocoapods.paths.frameworks="$FRAMEWORK_SEARCH_PATHS" + SCRIPT + } + ] +end \ No newline at end of file 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 64f072a85..f52c0a22e 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 @@ -78,14 +78,9 @@ actual class FirebaseAuth internal constructor(val android: com.google.firebase. actual open class AuthCredential(open val android: com.google.firebase.auth.AuthCredential) { actual val providerId: String get() = android.provider - actual val signInMethod: String - get() = android.signInMethod } -actual class PhoneAuthCredential(override val android: com.google.firebase.auth.PhoneAuthCredential) : AuthCredential(android) { - actual val smsCode: String? - get() = android.smsCode -} +actual class PhoneAuthCredential(override val android: com.google.firebase.auth.PhoneAuthCredential) : AuthCredential(android) actual class AuthResult internal constructor(val android: com.google.firebase.auth.AuthResult) { actual val user: FirebaseUser? @@ -150,11 +145,14 @@ actual class FirebaseUser internal constructor(val android: com.google.firebase. val request = actionCodeSettings?.android?.let { android.sendEmailVerification(it) } ?: android.sendEmailVerification() request.await().run { Unit } } - actual suspend fun unlink(provider: String): AuthResult = AuthResult(android.unlink(provider).await()) + actual suspend fun unlink(provider: String): FirebaseUser? = android.unlink(provider).await().user?.let { FirebaseUser(it) } actual suspend fun updateEmail(email: String) = android.updateEmail(email).await().run { Unit } actual suspend fun updatePassword(password: String) = android.updatePassword(password).await().run { Unit } actual suspend fun updatePhoneNumber(credential: PhoneAuthCredential) = android.updatePhoneNumber(credential.android).await().run { Unit } - actual suspend fun updateProfile(request: UserProfileChangeRequest) = android.updateProfile(request.android).await().run { Unit } + actual suspend fun updateProfile(buildRequest: (UserProfileChangeRequest.Builder) -> Unit) { + val request = UserProfileChangeRequest.Builder().apply { buildRequest(this) }.build() + android.updateProfile(request.android).await() + } actual suspend fun verifyBeforeUpdateEmail(newEmail: String, actionCodeSettings: ActionCodeSettings?) = android.verifyBeforeUpdateEmail(newEmail, actionCodeSettings?.android).await().run { Unit } } 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 9f71c200e..8a88dc51d 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 @@ -78,11 +78,8 @@ expect class FirebaseAuthWebException : FirebaseAuthException expect open class AuthCredential { val providerId: String - val signInMethod: String -} -expect class PhoneAuthCredential : AuthCredential { - val smsCode: String? } +expect class PhoneAuthCredential : AuthCredential expect object EmailAuthProvider{ fun credentialWithEmail(email: String, password: String): AuthCredential @@ -107,11 +104,11 @@ expect class FirebaseUser { suspend fun reauthenticate(credential: AuthCredential) suspend fun reauthenticateAndRetrieveData(credential: AuthCredential): AuthResult suspend fun sendEmailVerification(actionCodeSettings: ActionCodeSettings? = null) - suspend fun unlink(provider: String): AuthResult + suspend fun unlink(provider: String): FirebaseUser? suspend fun updateEmail(email: String) suspend fun updatePassword(password: String) suspend fun updatePhoneNumber(credential: PhoneAuthCredential) - suspend fun updateProfile(request: UserProfileChangeRequest) + suspend fun updateProfile(buildRequest: (UserProfileChangeRequest.Builder) -> Unit) suspend fun verifyBeforeUpdateEmail(newEmail: String, actionCodeSettings: ActionCodeSettings? = null) } 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 7317a1e89..30bd8fa8f 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 @@ -26,16 +26,41 @@ actual class FirebaseAuth internal constructor(val ios: FIRAuth) { actual val currentUser: FirebaseUser? get() = ios.currentUser?.let { FirebaseUser(it) } - actual suspend fun sendPasswordResetEmail(email: String) { - ios.await { sendPasswordResetWithEmail(email = email, completion = it) } + actual val authStateChanged get() = callbackFlow { + val handle = ios.addAuthStateDidChangeListener { _, user -> offer(user?.let { FirebaseUser(it) }) } + awaitClose { ios.removeAuthStateDidChangeListener(handle) } } - actual suspend fun signInWithEmailAndPassword(email: String, password: String) = - AuthResult(ios.awaitResult { signInWithEmail(email = email, password = password, completion = it) }) + actual val idTokenChanged get() = callbackFlow { + val handle = ios.addIDTokenDidChangeListener { _, user -> offer(user?.let { FirebaseUser(it) }) } + awaitClose { ios.removeIDTokenDidChangeListener(handle) } + } + + actual var languageCode: String + get() = ios.languageCode ?: "" + set(value) { ios.setLanguageCode(value) } + + actual suspend fun applyActionCode(code: String) = ios.await { applyActionCode(code, it) }.run { Unit } + actual suspend fun checkActionCode(code: String): ActionCodeResult = ActionCodeResult(ios.awaitResult { checkActionCode(code, it) }) + actual suspend fun confirmPasswordReset(code: String, newPassword: String) = ios.await { confirmPasswordResetWithCode(code, newPassword, it) }.run { Unit } actual suspend fun createUserWithEmailAndPassword(email: String, password: String) = AuthResult(ios.awaitResult { createUserWithEmail(email = email, password = password, completion = it) }) + actual suspend fun fetchSignInMethodsForEmail(email: String): SignInMethodQueryResult { + val signInMethods: List<*> = ios.awaitResult { fetchSignInMethodsForEmail(email, it) } + return SignInMethodQueryResult(signInMethods.mapNotNull { it as String }) + } + + actual suspend fun sendPasswordResetEmail(email: String, actionCodeSettings: ActionCodeSettings?) { + ios.await { actionCodeSettings?.let { actionSettings -> sendPasswordResetWithEmail(email, actionSettings.ios, it) } ?: sendPasswordResetWithEmail(email = email, completion = it) } + } + + actual suspend fun sendSignInLinkToEmail(email: String, actionCodeSettings: ActionCodeSettings) = ios.await { sendSignInLinkToEmail(email, actionCodeSettings.ios, it) }.run { Unit } + + actual suspend fun signInWithEmailAndPassword(email: String, password: String) = + AuthResult(ios.awaitResult { signInWithEmail(email = email, password = password, completion = it) }) + actual suspend fun signInWithCustomToken(token: String) = AuthResult(ios.awaitResult { signInWithCustomToken(token, it) }) @@ -47,10 +72,8 @@ actual class FirebaseAuth internal constructor(val ios: FIRAuth) { actual suspend fun signOut() = ios.throwError { signOut(it) }.run { Unit } - actual val authStateChanged get() = callbackFlow { - val handle = ios.addAuthStateDidChangeListener { _, user -> offer(user?.let { FirebaseUser(it) }) } - awaitClose { ios.removeAuthStateDidChangeListener(handle) } - } + actual suspend fun updateCurrentUser(user: FirebaseUser) = ios.await { updateCurrentUser(user.ios, it) }.run { Unit } + actual suspend fun verifyPasswordResetCode(code: String): String = ios.awaitResult { verifyPasswordResetCode(code, it) } } actual class AuthResult internal constructor(val ios: FIRAuthDataResult) { @@ -58,6 +81,28 @@ actual class AuthResult internal constructor(val ios: FIRAuthDataResult) { get() = FirebaseUser(ios.user) } +actual class ActionCodeResult(val ios: FIRActionCodeInfo) { + actual val operation: Operation + get() = when (ios.operation) { + FIRActionCodeOperationPasswordReset -> Operation.PasswordReset + FIRActionCodeOperationVerifyEmail -> Operation.VerifyEmail + FIRActionCodeOperationRecoverEmail -> Operation.RecoverEmail + FIRActionCodeOperationUnknown-> Operation.Error + FIRActionCodeOperationEmailLink -> Operation.SignInWithEmailLink + FIRActionCodeOperationVerifyAndChangeEmail -> Operation.VerifyBeforeChangeEmail + FIRActionCodeOperationRevertSecondFactorAddition -> Operation.RevertSecondFactorAddition + else -> Operation.Error + } + actual fun > getData(type: A): T? = when (type) { + is ActionCodeDataType.Email -> ios.email + is ActionCodeDataType.PreviousEmail -> ios.previousEmail + is ActionCodeDataType.MultiFactor -> null + else -> null + } as? T +} + +actual class SignInMethodQueryResult(actual val signInMethods: List) + actual class FirebaseUser internal constructor(val ios: FIRUser) { actual val uid: String get() = ios.uid @@ -67,13 +112,91 @@ actual class FirebaseUser internal constructor(val ios: FIRUser) { get() = ios.email actual val phoneNumber: String? get() = ios.phoneNumber + actual val photoURL: String? + get() = ios.photoURL?.absoluteString actual val isAnonymous: Boolean - get() = ios.isAnonymous() + get() = ios.anonymous actual val isEmailVerified: Boolean get() = ios.emailVerified + actual val metaData: MetaData? + get() = MetaData(ios.metadata) + actual val multiFactor: MultiFactor + get() = MultiFactor(ios.multiFactor) + actual val providerData: List + get() = ios.providerData.mapNotNull { provider -> (provider as? FIRUserInfoProtocol)?.let { UserInfo(it) } } + actual val providerId: String + get() = ios.providerID actual suspend fun delete() = ios.await { deleteWithCompletion(it) }.run { Unit } actual suspend fun reload() = ios.await { reloadWithCompletion(it) }.run { Unit } - actual suspend fun sendEmailVerification() = ios.await { sendEmailVerificationWithCompletion(it) }.run { Unit } + actual suspend fun getIdToken(forceRefresh: Boolean) { + val token: String = ios.awaitResult { getIDTokenForcingRefresh(forceRefresh, it) } + } + actual suspend fun linkWithCredential(credential: AuthCredential): AuthResult = AuthResult(ios.awaitResult { linkWithCredential(credential.ios, it) }) + actual suspend fun reauthenticate(credential: AuthCredential) { + val result: FIRAuthDataResult = ios.awaitResult { reauthenticateWithCredential(credential.ios, it) } + } + actual suspend fun reauthenticateAndRetrieveData(credential: AuthCredential): AuthResult = AuthResult(ios.awaitResult { reauthenticateAndRetrieveDataWithCredential(credential.ios, it) }) + + actual suspend fun sendEmailVerification(actionCodeSettings: ActionCodeSettings?) = ios.await { + actionCodeSettings?.let { actionSettings -> sendEmailVerificationWithActionCodeSettings(actionSettings.ios, it) } ?: sendEmailVerificationWithCompletion(it) + }.run { Unit } + actual suspend fun unlink(provider: String): FirebaseUser? { + val user: FIRUser? = ios.awaitResult { unlinkFromProvider(provider, it) } + return user?.let { + FirebaseUser(it) + } + } + actual suspend fun updateEmail(email: String) = ios.await { updateEmail(email, it) }.run { Unit } + actual suspend fun updatePassword(password: String) = ios.await { updatePassword(password, it) }.run { Unit } + actual suspend fun updatePhoneNumber(credential: PhoneAuthCredential) = ios.await { updatePhoneNumberCredential(credential.ios, it) }.run { Unit } + actual suspend fun updateProfile(buildRequest: (UserProfileChangeRequest.Builder) -> Unit) { + val request = UserProfileChangeRequest.Builder(this.ios).apply { buildRequest(this) }.build() + ios.await { request.ios.commitChangesWithCompletion(it) } + } + actual suspend fun verifyBeforeUpdateEmail(newEmail: String, actionCodeSettings: ActionCodeSettings?) = ios.await { + actionCodeSettings?.let { actionSettings -> sendEmailVerificationBeforeUpdatingEmail(newEmail, actionSettings.ios, it) } ?: sendEmailVerificationBeforeUpdatingEmail(newEmail, it) + }.run { Unit } +} + +actual class UserInfo(val ios: FIRUserInfoProtocol) { + actual val displayName: String? + get() = ios.displayName + actual val email: String? + get() = ios.email + actual val phoneNumber: String? + get() = ios.phoneNumber + actual val photoURL: String? + get() = ios.photoURL?.absoluteString + actual val providerId: String + get() = ios.providerID + actual val uid: String + get() = ios.uid +} + +actual class MetaData(val ios: FIRUserMetadata) { + actual val creationTime: Long? + get() = ios.creationDate?.timeIntervalSinceReferenceDate?.toLong() + actual val lastSignInTime: Long? + get() = ios.lastSignInDate?.timeIntervalSinceReferenceDate?.toLong() +} + +actual class UserProfileChangeRequest(val ios: FIRUserProfileChangeRequest) { + actual class Builder(private val user: FIRUser) { + + private val request = user.profileChangeRequest() + + actual fun setDisplayName(displayName: String?): Builder = apply { + request.setDisplayName(displayName) + } + actual fun setPhotoURL(photoURL: String?): Builder = apply { + request.setPhotoURL(photoURL?.let { NSURL.URLWithString(it) }) + } + actual fun build(): UserProfileChangeRequest = UserProfileChangeRequest(request) + } + actual val displayName: String? + get() = ios.displayName + actual val photoURL: String? + get() = ios.photoURL?.absoluteString } actual open class FirebaseAuthException(message: String): FirebaseException(message) @@ -81,11 +204,18 @@ actual open class FirebaseAuthActionCodeException(message: String): FirebaseAuth actual open class FirebaseAuthEmailException(message: String): FirebaseAuthException(message) actual open class FirebaseAuthInvalidCredentialsException(message: String): FirebaseAuthException(message) actual open class FirebaseAuthInvalidUserException(message: String): FirebaseAuthException(message) +actual open class FirebaseAuthMultiFactorException(message: String): FirebaseAuthException(message) actual open class FirebaseAuthRecentLoginRequiredException(message: String): FirebaseAuthException(message) actual open class FirebaseAuthUserCollisionException(message: String): FirebaseAuthException(message) +actual open class FirebaseAuthWeakPasswordException(message: String): FirebaseAuthException(message) actual open class FirebaseAuthWebException(message: String): FirebaseAuthException(message) -actual class AuthCredential(val ios: FIRAuthCredential) +actual open class AuthCredential(open val ios: FIRAuthCredential) { + actual val providerId: String + get() = ios.provider +} + +actual class PhoneAuthCredential(override val ios: FIRPhoneAuthCredential) : AuthCredential(ios) actual object EmailAuthProvider { actual fun credentialWithEmail( @@ -95,6 +225,67 @@ actual object EmailAuthProvider { AuthCredential(FIREmailAuthProvider.credentialWithEmail(email = email, password = password)) } +actual class MultiFactor(val ios: FIRMultiFactor) { + actual val enrolledFactors: List + get() = ios.enrolledFactors.mapNotNull { info -> (info as? FIRMultiFactorInfo)?.let{ MultiFactorInfo(it) } } + actual suspend fun enroll(multiFactorAssertion: MultiFactorAssertion, displayName: String?) = ios.await { enrollWithAssertion(multiFactorAssertion.ios, displayName, it) }.run { Unit } + actual suspend fun getSession(): MultiFactorSession = MultiFactorSession(ios.awaitResult { getSessionWithCompletion(completion = it) }) + actual suspend fun unenroll(multiFactorInfo: MultiFactorInfo) = ios.await { unenrollWithInfo(multiFactorInfo.ios, it) }.run { Unit } + actual suspend fun unenroll(factorUid: String) = ios.await { unenrollWithFactorUID(factorUid, it) }.run { Unit } +} + +actual class MultiFactorInfo(val ios: FIRMultiFactorInfo) { + actual val displayName: String? + get() = ios.displayName + actual val enrollmentTime: Long + get() = ios.enrollmentDate.timeIntervalSinceReferenceDate.toLong() + actual val factorId: String + get() = ios.factorID + actual val uid: String + get() = ios.UID +} + +actual class MultiFactorAssertion(val ios: FIRMultiFactorAssertion) { + actual val factorId: String + get() = ios.factorID +} + +actual class MultiFactorSession(val ios: FIRMultiFactorSession) + +actual class ActionCodeSettings private constructor(val ios: FIRActionCodeSettings) { + actual class Builder(val ios: FIRActionCodeSettings = FIRActionCodeSettings()) { + actual fun setAndroidPackageName(androidPackageName: String, installIfNotAvailable: Boolean, minimumVersion: String?): Builder = apply { + ios.setAndroidPackageName(androidPackageName, installIfNotAvailable, minimumVersion) + } + actual fun setDynamicLinkDomain(dynamicLinkDomain: String): Builder = apply { + ios.setDynamicLinkDomain(dynamicLinkDomain) + } + actual fun setHandleCodeInApp(status: Boolean): Builder = apply { + ios.setHandleCodeInApp(status) + } + actual fun setIOSBundleId(iOSBundleId: String): Builder = apply { + ios.setIOSBundleID(iOSBundleId) + } + actual fun setUrl(url: String): Builder = apply { + ios.setURL(NSURL.URLWithString(url)) + } + actual fun build(): ActionCodeSettings = ActionCodeSettings(ios) + } + + actual val canHandleCodeInApp: Boolean + get() = ios.handleCodeInApp() + actual val androidInstallApp: Boolean + get() = ios.androidInstallIfNotAvailable + actual val androidMinimumVersion: String? + get() = ios.androidMinimumVersion + actual val androidPackageName: String? + get() = ios.androidPackageName + actual val iOSBundle: String? + get() = ios.iOSBundleID + actual val url: String + get() = ios.URL?.absoluteString ?: "" +} + private fun T.throwError(block: T.(errorPointer: CPointer>) -> R): R { memScoped { @@ -146,6 +337,8 @@ private fun NSError.toException() = when(domain) { FIRAuthErrorCodeRequiresRecentLogin -> FirebaseAuthRecentLoginRequiredException(toString()) + FIRAuthErrorCodeMultiFactorInfoNotFound -> FirebaseAuthMultiFactorException(toString()) + FIRAuthErrorCodeEmailAlreadyInUse, FIRAuthErrorCodeAccountExistsWithDifferentCredential, FIRAuthErrorCodeCredentialAlreadyInUse -> FirebaseAuthUserCollisionException(toString()) diff --git a/firebase-database/build.gradle.kts b/firebase-database/build.gradle.kts index 0454cf4c3..f3419f0b6 100644 --- a/firebase-database/build.gradle.kts +++ b/firebase-database/build.gradle.kts @@ -71,7 +71,7 @@ kotlin { } val androidMain by getting { dependencies { - api("com.google.firebase:firebase-database:19.3.0") + api("com.google.firebase:firebase-database:19.3.1") } } val jsMain by getting {} @@ -83,7 +83,9 @@ kotlin { val firebaseDatabase by cinterops.creating { packageName("cocoapods.FirebaseDatabase") defFile(file("$projectDir/src/iosMain/c_interop/FirebaseDatabase.def")) - compilerOpts("-F${rootProject.buildDir}/Firebase/FirebaseDatabase") + compilerOpts("-F${rootProject.buildDir}/Firebase/FirebaseDatabase/FirebaseDatabase.xcframework/ios-armv7_arm64", + "-F${rootProject.buildDir}/Firebase/FirebaseDatabase/FirebaseDatabase.xcframework/ios-i386_x86_64-simulator", + "-F${rootProject.buildDir}/Firebase/FirebaseDatabase/FirebaseDatabase.xcframework/ios-x86_64-maccatalyst") } } } diff --git a/firebase-firestore/build.gradle.kts b/firebase-firestore/build.gradle.kts index 4db6c1efa..cd6cf11d2 100644 --- a/firebase-firestore/build.gradle.kts +++ b/firebase-firestore/build.gradle.kts @@ -81,7 +81,9 @@ kotlin { val firebasefirestore by cinterops.creating { packageName("cocoapods.FirebaseFirestore") defFile(file("$projectDir/src/iosMain/c_interop/FirebaseFirestore.def")) - compilerOpts("-F${rootProject.buildDir}/Firebase/FirebaseFirestore") + compilerOpts("-F${rootProject.buildDir}/Firebase/FirebaseFirestore/FirebaseFirestore.xcframework/ios-armv7_arm64", + "-F${rootProject.buildDir}/Firebase/FirebaseFirestore/FirebaseFirestore.xcframework/ios-i386_x86_64-simulator", + "-F${rootProject.buildDir}/Firebase/FirebaseFirestore/FirebaseFirestore.xcframework/ios-x86_64-maccatalyst") } } } diff --git a/firebase-functions/build.gradle.kts b/firebase-functions/build.gradle.kts index 85ddf911d..a4385da0e 100644 --- a/firebase-functions/build.gradle.kts +++ b/firebase-functions/build.gradle.kts @@ -77,7 +77,9 @@ kotlin { val firebasefunctions by cinterops.creating { packageName("cocoapods.FirebaseFunctions") defFile(file("$projectDir/src/iosMain/c_interop/FirebaseFunctions.def")) - compilerOpts("-F${rootProject.buildDir}/Firebase/FirebaseFunctions") + compilerOpts("-F${rootProject.buildDir}/Firebase/FirebaseFunctions/FirebaseFunctions.xcframework/ios-armv7_arm64", + "-F${rootProject.buildDir}/Firebase/FirebaseFunctions/FirebaseFunctions.xcframework/ios-i386_x86_64-simulator", + "-F${rootProject.buildDir}/Firebase/FirebaseFunctions/FirebaseFunctions.xcframework/ios-x86_64-maccatalyst") } } } From 9263267761e7eb7f10525c902d6c413025d01ab6 Mon Sep 17 00:00:00 2001 From: Gijs van Veen Date: Wed, 12 Aug 2020 13:01:35 +0200 Subject: [PATCH 04/32] Add providers --- .../kotlin/dev/gitlive/firebase/auth/auth.kt | 149 ++-------------- .../dev/gitlive/firebase/auth/credentials.kt | 94 ++++++++++ .../dev/gitlive/firebase/auth/multifactor.kt | 34 ++++ .../kotlin/dev/gitlive/firebase/auth/user.kt | 90 ++++++++++ .../kotlin/dev/gitlive/firebase/auth/auth.kt | 103 ++--------- .../dev/gitlive/firebase/auth/credentials.kt | 60 +++++++ .../dev/gitlive/firebase/auth/multifactor.kt | 26 +++ .../kotlin/dev/gitlive/firebase/auth/user.kt | 56 ++++++ .../kotlin/dev/gitlive/firebase/auth/auth.kt | 167 ++---------------- .../dev/gitlive/firebase/auth/credentials.kt | 27 +++ .../dev/gitlive/firebase/auth/multifactor.kt | 37 ++++ .../kotlin/dev/gitlive/firebase/auth/user.kt | 104 +++++++++++ 12 files changed, 566 insertions(+), 381 deletions(-) create mode 100644 firebase-auth/src/androidMain/kotlin/dev/gitlive/firebase/auth/credentials.kt create mode 100644 firebase-auth/src/androidMain/kotlin/dev/gitlive/firebase/auth/multifactor.kt create mode 100644 firebase-auth/src/androidMain/kotlin/dev/gitlive/firebase/auth/user.kt create mode 100644 firebase-auth/src/commonMain/kotlin/dev/gitlive/firebase/auth/credentials.kt create mode 100644 firebase-auth/src/commonMain/kotlin/dev/gitlive/firebase/auth/multifactor.kt create mode 100644 firebase-auth/src/commonMain/kotlin/dev/gitlive/firebase/auth/user.kt create mode 100644 firebase-auth/src/iosMain/kotlin/dev/gitlive/firebase/auth/credentials.kt create mode 100644 firebase-auth/src/iosMain/kotlin/dev/gitlive/firebase/auth/multifactor.kt create mode 100644 firebase-auth/src/iosMain/kotlin/dev/gitlive/firebase/auth/user.kt 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 f52c0a22e..d875c03bd 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 @@ -4,10 +4,8 @@ package dev.gitlive.firebase.auth -import android.net.Uri import com.google.firebase.auth.ActionCodeEmailInfo import com.google.firebase.auth.ActionCodeMultiFactorInfo -import com.google.firebase.auth.EmailAuthProvider import com.google.firebase.auth.FirebaseAuth.AuthStateListener import dev.gitlive.firebase.Firebase import dev.gitlive.firebase.FirebaseApp @@ -75,13 +73,6 @@ actual class FirebaseAuth internal constructor(val android: com.google.firebase. actual suspend fun verifyPasswordResetCode(code: String): String = android.verifyPasswordResetCode(code).await() } -actual open class AuthCredential(open val android: com.google.firebase.auth.AuthCredential) { - actual val providerId: String - get() = android.provider -} - -actual class PhoneAuthCredential(override val android: com.google.firebase.auth.PhoneAuthCredential) : AuthCredential(android) - actual class AuthResult internal constructor(val android: com.google.firebase.auth.AuthResult) { actual val user: FirebaseUser? get() = android.user?.let { FirebaseUser(it) } @@ -112,133 +103,6 @@ actual class SignInMethodQueryResult(val android: com.google.firebase.auth.SignI get() = android.signInMethods ?: emptyList() } -actual class FirebaseUser internal constructor(val android: com.google.firebase.auth.FirebaseUser) { - actual val uid: String - get() = android.uid - actual val displayName: String? - get() = android.displayName - actual val email: String? - get() = android.email - actual val phoneNumber: String? - get() = android.phoneNumber - actual val photoURL: String? - get() = android.photoUrl?.toString() - actual val isAnonymous: Boolean - get() = android.isAnonymous - actual val isEmailVerified: Boolean - get() = android.isEmailVerified - actual val metaData: MetaData? - get() = android.metadata?.let{ MetaData(it) } - actual val multiFactor: MultiFactor - get() = MultiFactor(android.multiFactor) - actual val providerData: List - get() = android.providerData.map { UserInfo(it) } - actual val providerId: String - get() = android.providerId - actual suspend fun delete() = android.delete().await().run { Unit } - actual suspend fun reload() = android.reload().await().run { Unit } - actual suspend fun getIdToken(forceRefresh: Boolean) = android.getIdToken(forceRefresh).await().run { Unit } - actual suspend fun linkWithCredential(credential: AuthCredential): AuthResult = AuthResult(android.linkWithCredential(credential.android).await()) - actual suspend fun reauthenticate(credential: AuthCredential) = android.reauthenticate(credential.android).await().run { Unit } - actual suspend fun reauthenticateAndRetrieveData(credential: AuthCredential): AuthResult = AuthResult(android.reauthenticateAndRetrieveData(credential.android).await()) - actual suspend fun sendEmailVerification(actionCodeSettings: ActionCodeSettings?) { - val request = actionCodeSettings?.android?.let { android.sendEmailVerification(it) } ?: android.sendEmailVerification() - request.await().run { Unit } - } - actual suspend fun unlink(provider: String): FirebaseUser? = android.unlink(provider).await().user?.let { FirebaseUser(it) } - actual suspend fun updateEmail(email: String) = android.updateEmail(email).await().run { Unit } - actual suspend fun updatePassword(password: String) = android.updatePassword(password).await().run { Unit } - actual suspend fun updatePhoneNumber(credential: PhoneAuthCredential) = android.updatePhoneNumber(credential.android).await().run { Unit } - actual suspend fun updateProfile(buildRequest: (UserProfileChangeRequest.Builder) -> Unit) { - val request = UserProfileChangeRequest.Builder().apply { buildRequest(this) }.build() - android.updateProfile(request.android).await() - } - actual suspend fun verifyBeforeUpdateEmail(newEmail: String, actionCodeSettings: ActionCodeSettings?) = android.verifyBeforeUpdateEmail(newEmail, actionCodeSettings?.android).await().run { Unit } -} - -actual class UserInfo(val android: com.google.firebase.auth.UserInfo) { - actual val displayName: String? - get() = android.displayName - actual val email: String? - get() = android.email - actual val phoneNumber: String? - get() = android.phoneNumber - actual val photoURL: String? - get() = android.photoUrl?.toString() - actual val providerId: String - get() = android.providerId - actual val uid: String - get() = android.uid -} - -actual class MetaData(val android: com.google.firebase.auth.FirebaseUserMetadata) { - actual val creationTime: Long? - get() = android.creationTimestamp - actual val lastSignInTime: Long? - get() = android.lastSignInTimestamp -} - -actual class UserProfileChangeRequest(val android: com.google.firebase.auth.UserProfileChangeRequest) { - actual class Builder(val android: com.google.firebase.auth.UserProfileChangeRequest.Builder = com.google.firebase.auth.UserProfileChangeRequest.Builder()) { - actual fun setDisplayName(displayName: String?): Builder = apply { - android.setDisplayName(displayName) - } - actual fun setPhotoURL(photoURL: String?): Builder = apply { - android.setPhotoUri(photoURL?.let { Uri.parse(it) }) - } - actual fun build(): UserProfileChangeRequest = UserProfileChangeRequest(android.build()) - } - actual val displayName: String? - get() = android.displayName - actual val photoURL: String? - get() = android.photoUri?.toString() -} - -actual typealias FirebaseAuthException = com.google.firebase.auth.FirebaseAuthException -actual typealias FirebaseAuthActionCodeException = com.google.firebase.auth.FirebaseAuthActionCodeException -actual typealias FirebaseAuthEmailException = com.google.firebase.auth.FirebaseAuthEmailException -actual typealias FirebaseAuthInvalidCredentialsException = com.google.firebase.auth.FirebaseAuthInvalidCredentialsException -actual typealias FirebaseAuthInvalidUserException = com.google.firebase.auth.FirebaseAuthInvalidUserException -actual typealias FirebaseAuthMultiFactorException = com.google.firebase.auth.FirebaseAuthMultiFactorException -actual typealias FirebaseAuthRecentLoginRequiredException = com.google.firebase.auth.FirebaseAuthRecentLoginRequiredException -actual typealias FirebaseAuthUserCollisionException = com.google.firebase.auth.FirebaseAuthUserCollisionException -actual typealias FirebaseAuthWeakPasswordException = com.google.firebase.auth.FirebaseAuthWeakPasswordException -actual typealias FirebaseAuthWebException = com.google.firebase.auth.FirebaseAuthWebException - -actual object EmailAuthProvider { - actual fun credentialWithEmail( - email: String, - password: String - ): AuthCredential = AuthCredential(EmailAuthProvider.getCredential(email, password)) -} - -actual class MultiFactor(val android: com.google.firebase.auth.MultiFactor) { - actual val enrolledFactors: List - get() = android.enrolledFactors.map { MultiFactorInfo(it) } - actual suspend fun enroll(multiFactorAssertion: MultiFactorAssertion, displayName: String?) = android.enroll(multiFactorAssertion.android, displayName).await().run { Unit } - actual suspend fun getSession(): MultiFactorSession = MultiFactorSession(android.session.await()) - actual suspend fun unenroll(multiFactorInfo: MultiFactorInfo) = android.unenroll(multiFactorInfo.android).await().run { Unit } - actual suspend fun unenroll(factorUid: String) = android.unenroll(factorUid).await().run { Unit } -} - -actual class MultiFactorInfo(val android: com.google.firebase.auth.MultiFactorInfo) { - actual val displayName: String? - get() = android.displayName - actual val enrollmentTime: Long - get() = android.enrollmentTimestamp - actual val factorId: String - get() = android.factorId - actual val uid: String - get() = android.uid -} - -actual class MultiFactorAssertion(val android: com.google.firebase.auth.MultiFactorAssertion) { - actual val factorId: String - get() = android.factorId -} - -actual class MultiFactorSession(val android: com.google.firebase.auth.MultiFactorSession) - actual class ActionCodeSettings private constructor(val android: com.google.firebase.auth.ActionCodeSettings) { actual class Builder(val android: com.google.firebase.auth.ActionCodeSettings.Builder = com.google.firebase.auth.ActionCodeSettings.newBuilder()) { actual fun setAndroidPackageName(androidPackageName: String, installIfNotAvailable: Boolean, minimumVersion: String?): Builder = apply { @@ -271,4 +135,15 @@ actual class ActionCodeSettings private constructor(val android: com.google.fire get() = android.iosBundle actual val url: String get() = android.url -} \ No newline at end of file +} + +actual typealias FirebaseAuthException = com.google.firebase.auth.FirebaseAuthException +actual typealias FirebaseAuthActionCodeException = com.google.firebase.auth.FirebaseAuthActionCodeException +actual typealias FirebaseAuthEmailException = com.google.firebase.auth.FirebaseAuthEmailException +actual typealias FirebaseAuthInvalidCredentialsException = com.google.firebase.auth.FirebaseAuthInvalidCredentialsException +actual typealias FirebaseAuthInvalidUserException = com.google.firebase.auth.FirebaseAuthInvalidUserException +actual typealias FirebaseAuthMultiFactorException = com.google.firebase.auth.FirebaseAuthMultiFactorException +actual typealias FirebaseAuthRecentLoginRequiredException = com.google.firebase.auth.FirebaseAuthRecentLoginRequiredException +actual typealias FirebaseAuthUserCollisionException = com.google.firebase.auth.FirebaseAuthUserCollisionException +actual typealias FirebaseAuthWeakPasswordException = com.google.firebase.auth.FirebaseAuthWeakPasswordException +actual typealias FirebaseAuthWebException = com.google.firebase.auth.FirebaseAuthWebException diff --git a/firebase-auth/src/androidMain/kotlin/dev/gitlive/firebase/auth/credentials.kt b/firebase-auth/src/androidMain/kotlin/dev/gitlive/firebase/auth/credentials.kt new file mode 100644 index 000000000..a47b14d88 --- /dev/null +++ b/firebase-auth/src/androidMain/kotlin/dev/gitlive/firebase/auth/credentials.kt @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2020 GitLive Ltd. Use of this source code is governed by the Apache 2.0 license. + */ + +package dev.gitlive.firebase.auth + +import android.app.Activity +import kotlinx.coroutines.tasks.await + +actual open class AuthCredential(open val android: com.google.firebase.auth.AuthCredential) { + actual val providerId: String + get() = android.provider +} + +actual class PhoneAuthCredential(override val android: com.google.firebase.auth.PhoneAuthCredential) : AuthCredential(android) + +actual class OAuthCredential(override val android: com.google.firebase.auth.OAuthCredential) : AuthCredential(android) + +actual object EmailAuthProvider { + actual fun credentialWithEmail( + email: String, + password: String + ): AuthCredential = AuthCredential(com.google.firebase.auth.EmailAuthProvider.getCredential(email, password)) +} + +actual object FacebookAuthProvider { + actual fun credentialWithAccessToken(accessToken: String): AuthCredential = AuthCredential(com.google.firebase.auth.FacebookAuthProvider.getCredential(accessToken)) +} + +actual object GithubAuthProvider { + actual fun credentialWithToken(token: String): AuthCredential = AuthCredential(com.google.firebase.auth.GithubAuthProvider.getCredential(token)) +} + +actual object GoogleAuthProvider { + actual fun credentialWithIDAndAccessToken(idToken: String, accessToken: String): AuthCredential = AuthCredential(com.google.firebase.auth.GoogleAuthProvider.getCredential(idToken, accessToken)) +} + +actual class OAuthProvider(val android: com.google.firebase.auth.OAuthProvider.Builder, private val auth: FirebaseAuth) { + actual constructor(provider: String, auth: FirebaseAuth) : this(com.google.firebase.auth.OAuthProvider.newBuilder(provider, auth.android), auth) + + actual companion object { + actual fun credentialsWithAccessToken(providerId: String, accessToken: String): AuthCredential = createCredentials(providerId) { + this.accessToken = accessToken + } + actual fun credentialsWithIDAndAccessToken(providerId: String, idToken: String, accessToken: String): AuthCredential = createCredentials(providerId) { + setIdToken(idToken) + this.accessToken = accessToken + } + actual fun credentialsWithIDRawNonceAndAccessToken(providerId: String, idToken: String, rawNonce: String, accessToken: String): AuthCredential = createCredentials(providerId) { + setIdTokenWithRawNonce(idToken, rawNonce) + this.accessToken = accessToken + } + actual fun credentialsWithIDAndRawNonce(providerId: String, idToken: String, rawNonce: String): AuthCredential = createCredentials(providerId) { + setIdTokenWithRawNonce(idToken, rawNonce) + } + + private fun createCredentials(providerId: String, block: com.google.firebase.auth.OAuthProvider.CredentialBuilder.() -> Unit): AuthCredential { + val credential = com.google.firebase.auth.OAuthProvider.newCredentialBuilder(providerId).apply { + block() + }.build() + return (credential as? com.google.firebase.auth.OAuthCredential)?.let { OAuthCredential(it) } ?: AuthCredential(credential) + } + } + + actual fun addScope(vararg scope: String) { + android.scopes = android.scopes + scope.asList() + } + actual fun addCustomParameter(key: String, value: String) { + android.addCustomParameter(key, value) + } + actual fun addCustomParameters(parameters: Map) { + android.addCustomParameters(parameters) + } + + actual suspend fun signIn(signInProvider: SignInProvider): AuthResult = AuthResult(auth.android.startActivityForSignInWithProvider(signInProvider, android.build()).await()) +} + +actual typealias SignInProvider = Activity + +actual class PhoneAuthProvider(val android: com.google.firebase.auth.PhoneAuthProvider) { + + actual companion object { + actual fun credentialWithVerificationIdAndSmsCode(verificationId: String, smsCode: String): PhoneAuthCredential = PhoneAuthCredential(com.google.firebase.auth.PhoneAuthProvider.getCredential(verificationId, smsCode)) + } + + actual constructor(auth: FirebaseAuth) : this(com.google.firebase.auth.PhoneAuthProvider.getInstance(auth.android)) + + fun test() { + } +} + +expect object TwitterAuthProvider { + fun credentialWithTokenAndSecret(token: String, secret: String): AuthCredential +} diff --git a/firebase-auth/src/androidMain/kotlin/dev/gitlive/firebase/auth/multifactor.kt b/firebase-auth/src/androidMain/kotlin/dev/gitlive/firebase/auth/multifactor.kt new file mode 100644 index 000000000..2b553adf5 --- /dev/null +++ b/firebase-auth/src/androidMain/kotlin/dev/gitlive/firebase/auth/multifactor.kt @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2020 GitLive Ltd. Use of this source code is governed by the Apache 2.0 license. + */ + +package dev.gitlive.firebase.auth + +import kotlinx.coroutines.tasks.await + +actual class MultiFactor(val android: com.google.firebase.auth.MultiFactor) { + actual val enrolledFactors: List + get() = android.enrolledFactors.map { MultiFactorInfo(it) } + actual suspend fun enroll(multiFactorAssertion: MultiFactorAssertion, displayName: String?) = android.enroll(multiFactorAssertion.android, displayName).await().run { Unit } + actual suspend fun getSession(): MultiFactorSession = MultiFactorSession(android.session.await()) + actual suspend fun unenroll(multiFactorInfo: MultiFactorInfo) = android.unenroll(multiFactorInfo.android).await().run { Unit } + actual suspend fun unenroll(factorUid: String) = android.unenroll(factorUid).await().run { Unit } +} + +actual class MultiFactorInfo(val android: com.google.firebase.auth.MultiFactorInfo) { + actual val displayName: String? + get() = android.displayName + actual val enrollmentTime: Long + get() = android.enrollmentTimestamp + actual val factorId: String + get() = android.factorId + actual val uid: String + get() = android.uid +} + +actual class MultiFactorAssertion(val android: com.google.firebase.auth.MultiFactorAssertion) { + actual val factorId: String + get() = android.factorId +} + +actual class MultiFactorSession(val android: com.google.firebase.auth.MultiFactorSession) diff --git a/firebase-auth/src/androidMain/kotlin/dev/gitlive/firebase/auth/user.kt b/firebase-auth/src/androidMain/kotlin/dev/gitlive/firebase/auth/user.kt new file mode 100644 index 000000000..f211e6872 --- /dev/null +++ b/firebase-auth/src/androidMain/kotlin/dev/gitlive/firebase/auth/user.kt @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2020 GitLive Ltd. Use of this source code is governed by the Apache 2.0 license. + */ + +package dev.gitlive.firebase.auth + +import android.net.Uri +import kotlinx.coroutines.tasks.await + +actual class FirebaseUser internal constructor(val android: com.google.firebase.auth.FirebaseUser) { + actual val uid: String + get() = android.uid + actual val displayName: String? + get() = android.displayName + actual val email: String? + get() = android.email + actual val phoneNumber: String? + get() = android.phoneNumber + actual val photoURL: String? + get() = android.photoUrl?.toString() + actual val isAnonymous: Boolean + get() = android.isAnonymous + actual val isEmailVerified: Boolean + get() = android.isEmailVerified + actual val metaData: MetaData? + get() = android.metadata?.let{ MetaData(it) } + actual val multiFactor: MultiFactor + get() = MultiFactor(android.multiFactor) + actual val providerData: List + get() = android.providerData.map { UserInfo(it) } + actual val providerId: String + get() = android.providerId + actual suspend fun delete() = android.delete().await().run { Unit } + actual suspend fun reload() = android.reload().await().run { Unit } + actual suspend fun getIdToken(forceRefresh: Boolean) = android.getIdToken(forceRefresh).await().run { Unit } + actual suspend fun linkWithCredential(credential: AuthCredential): AuthResult = AuthResult(android.linkWithCredential(credential.android).await()) + actual suspend fun reauthenticate(credential: AuthCredential) = android.reauthenticate(credential.android).await().run { Unit } + actual suspend fun reauthenticateAndRetrieveData(credential: AuthCredential): AuthResult = AuthResult(android.reauthenticateAndRetrieveData(credential.android).await()) + actual suspend fun sendEmailVerification(actionCodeSettings: ActionCodeSettings?) { + val request = actionCodeSettings?.android?.let { android.sendEmailVerification(it) } ?: android.sendEmailVerification() + request.await().run { Unit } + } + actual suspend fun unlink(provider: String): FirebaseUser? = android.unlink(provider).await().user?.let { FirebaseUser(it) } + actual suspend fun updateEmail(email: String) = android.updateEmail(email).await().run { Unit } + actual suspend fun updatePassword(password: String) = android.updatePassword(password).await().run { Unit } + actual suspend fun updatePhoneNumber(credential: PhoneAuthCredential) = android.updatePhoneNumber(credential.android).await().run { Unit } + actual suspend fun updateProfile(buildRequest: (UserProfileChangeRequest.Builder) -> Unit) { + val request = UserProfileChangeRequest.Builder().apply { buildRequest(this) }.build() + android.updateProfile(request.android).await() + } + actual suspend fun verifyBeforeUpdateEmail(newEmail: String, actionCodeSettings: ActionCodeSettings?) = android.verifyBeforeUpdateEmail(newEmail, actionCodeSettings?.android).await().run { Unit } +} + +actual class UserInfo(val android: com.google.firebase.auth.UserInfo) { + actual val displayName: String? + get() = android.displayName + actual val email: String? + get() = android.email + actual val phoneNumber: String? + get() = android.phoneNumber + actual val photoURL: String? + get() = android.photoUrl?.toString() + actual val providerId: String + get() = android.providerId + actual val uid: String + get() = android.uid +} + +actual class MetaData(val android: com.google.firebase.auth.FirebaseUserMetadata) { + actual val creationTime: Long? + get() = android.creationTimestamp + actual val lastSignInTime: Long? + get() = android.lastSignInTimestamp +} + +actual class UserProfileChangeRequest(val android: com.google.firebase.auth.UserProfileChangeRequest) { + actual class Builder(val android: com.google.firebase.auth.UserProfileChangeRequest.Builder = com.google.firebase.auth.UserProfileChangeRequest.Builder()) { + actual fun setDisplayName(displayName: String?): Builder = apply { + android.setDisplayName(displayName) + } + actual fun setPhotoURL(photoURL: String?): Builder = apply { + android.setPhotoUri(photoURL?.let { Uri.parse(it) }) + } + actual fun build(): UserProfileChangeRequest = UserProfileChangeRequest(android.build()) + } + actual val displayName: String? + get() = android.displayName + actual val photoURL: String? + get() = android.photoUri?.toString() +} 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 8a88dc51d..5bc9014ba 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 @@ -65,98 +65,6 @@ sealed class ActionCodeDataType { object MultiFactor : ActionCodeDataType() } -expect open class FirebaseAuthException : FirebaseException -expect class FirebaseAuthActionCodeException : FirebaseAuthException -expect class FirebaseAuthEmailException : FirebaseAuthException -expect class FirebaseAuthInvalidCredentialsException : FirebaseAuthException -expect class FirebaseAuthInvalidUserException : FirebaseAuthException -expect class FirebaseAuthMultiFactorException: FirebaseAuthException -expect class FirebaseAuthRecentLoginRequiredException : FirebaseAuthException -expect class FirebaseAuthUserCollisionException : FirebaseAuthException -expect class FirebaseAuthWeakPasswordException : FirebaseAuthException -expect class FirebaseAuthWebException : FirebaseAuthException - -expect open class AuthCredential { - val providerId: String -} -expect class PhoneAuthCredential : AuthCredential - -expect object EmailAuthProvider{ - fun credentialWithEmail(email: String, password: String): AuthCredential -} - -expect class FirebaseUser { - val uid: String - val displayName: String? - val email: String? - val phoneNumber: String? - val photoURL: String? - val isAnonymous: Boolean - val isEmailVerified: Boolean - val metaData: MetaData? - val multiFactor: MultiFactor - val providerData: List - val providerId: String - suspend fun delete() - suspend fun reload() - suspend fun getIdToken(forceRefresh: Boolean) - suspend fun linkWithCredential(credential: AuthCredential): AuthResult - suspend fun reauthenticate(credential: AuthCredential) - suspend fun reauthenticateAndRetrieveData(credential: AuthCredential): AuthResult - suspend fun sendEmailVerification(actionCodeSettings: ActionCodeSettings? = null) - suspend fun unlink(provider: String): FirebaseUser? - suspend fun updateEmail(email: String) - suspend fun updatePassword(password: String) - suspend fun updatePhoneNumber(credential: PhoneAuthCredential) - suspend fun updateProfile(buildRequest: (UserProfileChangeRequest.Builder) -> Unit) - suspend fun verifyBeforeUpdateEmail(newEmail: String, actionCodeSettings: ActionCodeSettings? = null) -} - -expect class UserInfo { - val displayName: String? - val email: String? - val phoneNumber: String? - val photoURL: String? - val providerId: String - val uid: String -} - -expect class MetaData { - val creationTime: Long? - val lastSignInTime: Long? -} - -expect class UserProfileChangeRequest { - class Builder { - fun setDisplayName(displayName: String?): Builder - fun setPhotoURL(photoURL: String?): Builder - fun build(): UserProfileChangeRequest - } - val displayName: String? - val photoURL: String? -} - -expect class MultiFactor { - val enrolledFactors: List - suspend fun enroll(multiFactorAssertion: MultiFactorAssertion, displayName: String?) - suspend fun getSession(): MultiFactorSession - suspend fun unenroll(multiFactorInfo: MultiFactorInfo) - suspend fun unenroll(factorUid: String) -} - -expect class MultiFactorInfo { - val displayName: String? - val enrollmentTime: Long - val factorId: String - val uid: String -} - -expect class MultiFactorAssertion { - val factorId: String -} - -expect class MultiFactorSession - expect class ActionCodeSettings { class Builder { fun setAndroidPackageName(androidPackageName: String, installIfNotAvailable: Boolean, minimumVersion: String?): Builder @@ -174,3 +82,14 @@ expect class ActionCodeSettings { val iOSBundle: String? val url: String } + +expect open class FirebaseAuthException : FirebaseException +expect class FirebaseAuthActionCodeException : FirebaseAuthException +expect class FirebaseAuthEmailException : FirebaseAuthException +expect class FirebaseAuthInvalidCredentialsException : FirebaseAuthException +expect class FirebaseAuthInvalidUserException : FirebaseAuthException +expect class FirebaseAuthMultiFactorException: FirebaseAuthException +expect class FirebaseAuthRecentLoginRequiredException : FirebaseAuthException +expect class FirebaseAuthUserCollisionException : FirebaseAuthException +expect class FirebaseAuthWeakPasswordException : FirebaseAuthException +expect class FirebaseAuthWebException : FirebaseAuthException diff --git a/firebase-auth/src/commonMain/kotlin/dev/gitlive/firebase/auth/credentials.kt b/firebase-auth/src/commonMain/kotlin/dev/gitlive/firebase/auth/credentials.kt new file mode 100644 index 000000000..fa841029e --- /dev/null +++ b/firebase-auth/src/commonMain/kotlin/dev/gitlive/firebase/auth/credentials.kt @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2020 GitLive Ltd. Use of this source code is governed by the Apache 2.0 license. + */ + +package dev.gitlive.firebase.auth + +import dev.gitlive.firebase.Firebase + +expect open class AuthCredential { + val providerId: String +} +expect class PhoneAuthCredential : AuthCredential + +expect class OAuthCredential : AuthCredential + +expect object EmailAuthProvider { + fun credentialWithEmail(email: String, password: String): AuthCredential +} + +expect object FacebookAuthProvider { + fun credentialWithAccessToken(accessToken: String): AuthCredential +} + +expect object GithubAuthProvider { + fun credentialWithToken(token: String): AuthCredential +} + +expect object GoogleAuthProvider { + fun credentialWithIDAndAccessToken(idToken: String, accessToken: String): AuthCredential +} + +expect class OAuthProvider constructor(provider: String, auth: FirebaseAuth = Firebase.auth) { + companion object { + fun credentialsWithAccessToken(providerId: String, accessToken: String): AuthCredential + fun credentialsWithIDAndAccessToken(providerId: String, idToken: String, accessToken: String): AuthCredential + fun credentialsWithIDRawNonceAndAccessToken(providerId: String, idToken: String, rawNonce: String, accessToken: String): AuthCredential + fun credentialsWithIDAndRawNonce(providerId: String, idToken: String, rawNonce: String): AuthCredential + } + + fun addScope(vararg scope: String) + fun addCustomParameter(key: String, value: String) + fun addCustomParameters(parameters: Map) + + suspend fun signIn(signInProvider: SignInProvider): AuthResult +} + +expect class SignInProvider + +expect class PhoneAuthProvider constructor(auth: FirebaseAuth = Firebase.auth) { + companion object { + fun credentialWithVerificationIdAndSmsCode(verificationId: String, smsCode: String): PhoneAuthCredential + } + +} + +expect class PhoneVerificationProvider + +expect object TwitterAuthProvider { + fun credentialWithTokenAndSecret(token: String, secret: String): AuthCredential +} diff --git a/firebase-auth/src/commonMain/kotlin/dev/gitlive/firebase/auth/multifactor.kt b/firebase-auth/src/commonMain/kotlin/dev/gitlive/firebase/auth/multifactor.kt new file mode 100644 index 000000000..7b21e0b23 --- /dev/null +++ b/firebase-auth/src/commonMain/kotlin/dev/gitlive/firebase/auth/multifactor.kt @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2020 GitLive Ltd. Use of this source code is governed by the Apache 2.0 license. + */ + +package dev.gitlive.firebase.auth + +expect class MultiFactor { + val enrolledFactors: List + suspend fun enroll(multiFactorAssertion: MultiFactorAssertion, displayName: String?) + suspend fun getSession(): MultiFactorSession + suspend fun unenroll(multiFactorInfo: MultiFactorInfo) + suspend fun unenroll(factorUid: String) +} + +expect class MultiFactorInfo { + val displayName: String? + val enrollmentTime: Long + val factorId: String + val uid: String +} + +expect class MultiFactorAssertion { + val factorId: String +} + +expect class MultiFactorSession diff --git a/firebase-auth/src/commonMain/kotlin/dev/gitlive/firebase/auth/user.kt b/firebase-auth/src/commonMain/kotlin/dev/gitlive/firebase/auth/user.kt new file mode 100644 index 000000000..10bd85a96 --- /dev/null +++ b/firebase-auth/src/commonMain/kotlin/dev/gitlive/firebase/auth/user.kt @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2020 GitLive Ltd. Use of this source code is governed by the Apache 2.0 license. + */ + +package dev.gitlive.firebase.auth + +expect class FirebaseUser { + val uid: String + val displayName: String? + val email: String? + val phoneNumber: String? + val photoURL: String? + val isAnonymous: Boolean + val isEmailVerified: Boolean + val metaData: MetaData? + val multiFactor: MultiFactor + val providerData: List + val providerId: String + suspend fun delete() + suspend fun reload() + suspend fun getIdToken(forceRefresh: Boolean) + suspend fun linkWithCredential(credential: AuthCredential): AuthResult + suspend fun reauthenticate(credential: AuthCredential) + suspend fun reauthenticateAndRetrieveData(credential: AuthCredential): AuthResult + suspend fun sendEmailVerification(actionCodeSettings: ActionCodeSettings? = null) + suspend fun unlink(provider: String): FirebaseUser? + suspend fun updateEmail(email: String) + suspend fun updatePassword(password: String) + suspend fun updatePhoneNumber(credential: PhoneAuthCredential) + suspend fun updateProfile(buildRequest: (UserProfileChangeRequest.Builder) -> Unit) + suspend fun verifyBeforeUpdateEmail(newEmail: String, actionCodeSettings: ActionCodeSettings? = null) +} + +expect class UserInfo { + val displayName: String? + val email: String? + val phoneNumber: String? + val photoURL: String? + val providerId: String + val uid: String +} + +expect class MetaData { + val creationTime: Long? + val lastSignInTime: Long? +} + +expect class UserProfileChangeRequest { + class Builder { + fun setDisplayName(displayName: String?): Builder + fun setPhotoURL(photoURL: String?): Builder + fun build(): UserProfileChangeRequest + } + val displayName: String? + val photoURL: String? +} 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 30bd8fa8f..b97a435b0 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 @@ -103,155 +103,6 @@ actual class ActionCodeResult(val ios: FIRActionCodeInfo) { actual class SignInMethodQueryResult(actual val signInMethods: List) -actual class FirebaseUser internal constructor(val ios: FIRUser) { - actual val uid: String - get() = ios.uid - actual val displayName: String? - get() = ios.displayName - actual val email: String? - get() = ios.email - actual val phoneNumber: String? - get() = ios.phoneNumber - actual val photoURL: String? - get() = ios.photoURL?.absoluteString - actual val isAnonymous: Boolean - get() = ios.anonymous - actual val isEmailVerified: Boolean - get() = ios.emailVerified - actual val metaData: MetaData? - get() = MetaData(ios.metadata) - actual val multiFactor: MultiFactor - get() = MultiFactor(ios.multiFactor) - actual val providerData: List - get() = ios.providerData.mapNotNull { provider -> (provider as? FIRUserInfoProtocol)?.let { UserInfo(it) } } - actual val providerId: String - get() = ios.providerID - actual suspend fun delete() = ios.await { deleteWithCompletion(it) }.run { Unit } - actual suspend fun reload() = ios.await { reloadWithCompletion(it) }.run { Unit } - actual suspend fun getIdToken(forceRefresh: Boolean) { - val token: String = ios.awaitResult { getIDTokenForcingRefresh(forceRefresh, it) } - } - actual suspend fun linkWithCredential(credential: AuthCredential): AuthResult = AuthResult(ios.awaitResult { linkWithCredential(credential.ios, it) }) - actual suspend fun reauthenticate(credential: AuthCredential) { - val result: FIRAuthDataResult = ios.awaitResult { reauthenticateWithCredential(credential.ios, it) } - } - actual suspend fun reauthenticateAndRetrieveData(credential: AuthCredential): AuthResult = AuthResult(ios.awaitResult { reauthenticateAndRetrieveDataWithCredential(credential.ios, it) }) - - actual suspend fun sendEmailVerification(actionCodeSettings: ActionCodeSettings?) = ios.await { - actionCodeSettings?.let { actionSettings -> sendEmailVerificationWithActionCodeSettings(actionSettings.ios, it) } ?: sendEmailVerificationWithCompletion(it) - }.run { Unit } - actual suspend fun unlink(provider: String): FirebaseUser? { - val user: FIRUser? = ios.awaitResult { unlinkFromProvider(provider, it) } - return user?.let { - FirebaseUser(it) - } - } - actual suspend fun updateEmail(email: String) = ios.await { updateEmail(email, it) }.run { Unit } - actual suspend fun updatePassword(password: String) = ios.await { updatePassword(password, it) }.run { Unit } - actual suspend fun updatePhoneNumber(credential: PhoneAuthCredential) = ios.await { updatePhoneNumberCredential(credential.ios, it) }.run { Unit } - actual suspend fun updateProfile(buildRequest: (UserProfileChangeRequest.Builder) -> Unit) { - val request = UserProfileChangeRequest.Builder(this.ios).apply { buildRequest(this) }.build() - ios.await { request.ios.commitChangesWithCompletion(it) } - } - actual suspend fun verifyBeforeUpdateEmail(newEmail: String, actionCodeSettings: ActionCodeSettings?) = ios.await { - actionCodeSettings?.let { actionSettings -> sendEmailVerificationBeforeUpdatingEmail(newEmail, actionSettings.ios, it) } ?: sendEmailVerificationBeforeUpdatingEmail(newEmail, it) - }.run { Unit } -} - -actual class UserInfo(val ios: FIRUserInfoProtocol) { - actual val displayName: String? - get() = ios.displayName - actual val email: String? - get() = ios.email - actual val phoneNumber: String? - get() = ios.phoneNumber - actual val photoURL: String? - get() = ios.photoURL?.absoluteString - actual val providerId: String - get() = ios.providerID - actual val uid: String - get() = ios.uid -} - -actual class MetaData(val ios: FIRUserMetadata) { - actual val creationTime: Long? - get() = ios.creationDate?.timeIntervalSinceReferenceDate?.toLong() - actual val lastSignInTime: Long? - get() = ios.lastSignInDate?.timeIntervalSinceReferenceDate?.toLong() -} - -actual class UserProfileChangeRequest(val ios: FIRUserProfileChangeRequest) { - actual class Builder(private val user: FIRUser) { - - private val request = user.profileChangeRequest() - - actual fun setDisplayName(displayName: String?): Builder = apply { - request.setDisplayName(displayName) - } - actual fun setPhotoURL(photoURL: String?): Builder = apply { - request.setPhotoURL(photoURL?.let { NSURL.URLWithString(it) }) - } - actual fun build(): UserProfileChangeRequest = UserProfileChangeRequest(request) - } - actual val displayName: String? - get() = ios.displayName - actual val photoURL: String? - get() = ios.photoURL?.absoluteString -} - -actual open class FirebaseAuthException(message: String): FirebaseException(message) -actual open class FirebaseAuthActionCodeException(message: String): FirebaseAuthException(message) -actual open class FirebaseAuthEmailException(message: String): FirebaseAuthException(message) -actual open class FirebaseAuthInvalidCredentialsException(message: String): FirebaseAuthException(message) -actual open class FirebaseAuthInvalidUserException(message: String): FirebaseAuthException(message) -actual open class FirebaseAuthMultiFactorException(message: String): FirebaseAuthException(message) -actual open class FirebaseAuthRecentLoginRequiredException(message: String): FirebaseAuthException(message) -actual open class FirebaseAuthUserCollisionException(message: String): FirebaseAuthException(message) -actual open class FirebaseAuthWeakPasswordException(message: String): FirebaseAuthException(message) -actual open class FirebaseAuthWebException(message: String): FirebaseAuthException(message) - -actual open class AuthCredential(open val ios: FIRAuthCredential) { - actual val providerId: String - get() = ios.provider -} - -actual class PhoneAuthCredential(override val ios: FIRPhoneAuthCredential) : AuthCredential(ios) - -actual object EmailAuthProvider { - actual fun credentialWithEmail( - email: String, - password: String - ): AuthCredential = - AuthCredential(FIREmailAuthProvider.credentialWithEmail(email = email, password = password)) -} - -actual class MultiFactor(val ios: FIRMultiFactor) { - actual val enrolledFactors: List - get() = ios.enrolledFactors.mapNotNull { info -> (info as? FIRMultiFactorInfo)?.let{ MultiFactorInfo(it) } } - actual suspend fun enroll(multiFactorAssertion: MultiFactorAssertion, displayName: String?) = ios.await { enrollWithAssertion(multiFactorAssertion.ios, displayName, it) }.run { Unit } - actual suspend fun getSession(): MultiFactorSession = MultiFactorSession(ios.awaitResult { getSessionWithCompletion(completion = it) }) - actual suspend fun unenroll(multiFactorInfo: MultiFactorInfo) = ios.await { unenrollWithInfo(multiFactorInfo.ios, it) }.run { Unit } - actual suspend fun unenroll(factorUid: String) = ios.await { unenrollWithFactorUID(factorUid, it) }.run { Unit } -} - -actual class MultiFactorInfo(val ios: FIRMultiFactorInfo) { - actual val displayName: String? - get() = ios.displayName - actual val enrollmentTime: Long - get() = ios.enrollmentDate.timeIntervalSinceReferenceDate.toLong() - actual val factorId: String - get() = ios.factorID - actual val uid: String - get() = ios.UID -} - -actual class MultiFactorAssertion(val ios: FIRMultiFactorAssertion) { - actual val factorId: String - get() = ios.factorID -} - -actual class MultiFactorSession(val ios: FIRMultiFactorSession) - actual class ActionCodeSettings private constructor(val ios: FIRActionCodeSettings) { actual class Builder(val ios: FIRActionCodeSettings = FIRActionCodeSettings()) { actual fun setAndroidPackageName(androidPackageName: String, installIfNotAvailable: Boolean, minimumVersion: String?): Builder = apply { @@ -286,8 +137,18 @@ actual class ActionCodeSettings private constructor(val ios: FIRActionCodeSettin get() = ios.URL?.absoluteString ?: "" } +actual open class FirebaseAuthException(message: String): FirebaseException(message) +actual open class FirebaseAuthActionCodeException(message: String): FirebaseAuthException(message) +actual open class FirebaseAuthEmailException(message: String): FirebaseAuthException(message) +actual open class FirebaseAuthInvalidCredentialsException(message: String): FirebaseAuthException(message) +actual open class FirebaseAuthInvalidUserException(message: String): FirebaseAuthException(message) +actual open class FirebaseAuthMultiFactorException(message: String): FirebaseAuthException(message) +actual open class FirebaseAuthRecentLoginRequiredException(message: String): FirebaseAuthException(message) +actual open class FirebaseAuthUserCollisionException(message: String): FirebaseAuthException(message) +actual open class FirebaseAuthWeakPasswordException(message: String): FirebaseAuthException(message) +actual open class FirebaseAuthWebException(message: String): FirebaseAuthException(message) -private fun T.throwError(block: T.(errorPointer: CPointer>) -> R): R { +internal fun T.throwError(block: T.(errorPointer: CPointer>) -> R): R { memScoped { val errorPointer: CPointer> = alloc>().ptr val result = block(errorPointer) @@ -299,7 +160,7 @@ private fun T.throwError(block: T.(errorPointer: CPointer T.awaitResult(function: T.(callback: (R?, NSError?) -> Unit) -> Unit): R { +internal suspend fun T.awaitResult(function: T.(callback: (R?, NSError?) -> Unit) -> Unit): R { val job = CompletableDeferred() function { result, error -> if(result != null) { @@ -311,7 +172,7 @@ private suspend fun T.awaitResult(function: T.(callback: (R?, NSError?) - return job.await() } -private suspend fun T.await(function: T.(callback: (NSError?) -> Unit) -> Unit) { +internal suspend fun T.await(function: T.(callback: (NSError?) -> Unit) -> Unit) { val job = CompletableDeferred() function { error -> if(error == null) { @@ -343,6 +204,8 @@ private fun NSError.toException() = when(domain) { FIRAuthErrorCodeAccountExistsWithDifferentCredential, FIRAuthErrorCodeCredentialAlreadyInUse -> FirebaseAuthUserCollisionException(toString()) + FIRAuthErrorCodeWeakPassword -> FirebaseAuthWeakPasswordException(toString()) + FIRAuthErrorCodeWebContextAlreadyPresented, FIRAuthErrorCodeWebContextCancelled, FIRAuthErrorCodeWebInternalError -> FirebaseAuthWebException(toString()) diff --git a/firebase-auth/src/iosMain/kotlin/dev/gitlive/firebase/auth/credentials.kt b/firebase-auth/src/iosMain/kotlin/dev/gitlive/firebase/auth/credentials.kt new file mode 100644 index 000000000..2b3135055 --- /dev/null +++ b/firebase-auth/src/iosMain/kotlin/dev/gitlive/firebase/auth/credentials.kt @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2020 GitLive Ltd. Use of this source code is governed by the Apache 2.0 license. + */ + +package dev.gitlive.firebase.auth + +import cocoapods.FirebaseAuth.* + +actual open class AuthCredential(open val ios: FIRAuthCredential) { + actual val providerId: String + get() = ios.provider +} + +actual class PhoneAuthCredential(override val ios: FIRPhoneAuthCredential) : AuthCredential(ios) +actual class OAuthCredential(override val ios: FIROAuthCredential) : AuthCredential(ios) + +actual object EmailAuthProvider { + actual fun credentialWithEmail( + email: String, + password: String + ): AuthCredential = + AuthCredential(FIREmailAuthProvider.credentialWithEmail(email = email, password = password)) +} + +actual object FacebookAuthProvider { + actual fun credentialWithAccessToken(accessToken: String): AuthCredential = AuthCredential(FIRFacebookAuthProvider.credentialWithAccessToken(accessToken)) +} \ No newline at end of file diff --git a/firebase-auth/src/iosMain/kotlin/dev/gitlive/firebase/auth/multifactor.kt b/firebase-auth/src/iosMain/kotlin/dev/gitlive/firebase/auth/multifactor.kt new file mode 100644 index 000000000..1c1c2a7f6 --- /dev/null +++ b/firebase-auth/src/iosMain/kotlin/dev/gitlive/firebase/auth/multifactor.kt @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2020 GitLive Ltd. Use of this source code is governed by the Apache 2.0 license. + */ + +package dev.gitlive.firebase.auth + +import cocoapods.FirebaseAuth.FIRMultiFactor +import cocoapods.FirebaseAuth.FIRMultiFactorAssertion +import cocoapods.FirebaseAuth.FIRMultiFactorInfo +import cocoapods.FirebaseAuth.FIRMultiFactorSession + +actual class MultiFactor(val ios: FIRMultiFactor) { + actual val enrolledFactors: List + get() = ios.enrolledFactors.mapNotNull { info -> (info as? FIRMultiFactorInfo)?.let{ MultiFactorInfo(it) } } + actual suspend fun enroll(multiFactorAssertion: MultiFactorAssertion, displayName: String?) = ios.await { enrollWithAssertion(multiFactorAssertion.ios, displayName, it) }.run { Unit } + actual suspend fun getSession(): MultiFactorSession = MultiFactorSession(ios.awaitResult { getSessionWithCompletion(completion = it) }) + actual suspend fun unenroll(multiFactorInfo: MultiFactorInfo) = ios.await { unenrollWithInfo(multiFactorInfo.ios, it) }.run { Unit } + actual suspend fun unenroll(factorUid: String) = ios.await { unenrollWithFactorUID(factorUid, it) }.run { Unit } +} + +actual class MultiFactorInfo(val ios: FIRMultiFactorInfo) { + actual val displayName: String? + get() = ios.displayName + actual val enrollmentTime: Long + get() = ios.enrollmentDate.timeIntervalSinceReferenceDate.toLong() + actual val factorId: String + get() = ios.factorID + actual val uid: String + get() = ios.UID +} + +actual class MultiFactorAssertion(val ios: FIRMultiFactorAssertion) { + actual val factorId: String + get() = ios.factorID +} + +actual class MultiFactorSession(val ios: FIRMultiFactorSession) diff --git a/firebase-auth/src/iosMain/kotlin/dev/gitlive/firebase/auth/user.kt b/firebase-auth/src/iosMain/kotlin/dev/gitlive/firebase/auth/user.kt new file mode 100644 index 000000000..6adaddda1 --- /dev/null +++ b/firebase-auth/src/iosMain/kotlin/dev/gitlive/firebase/auth/user.kt @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2020 GitLive Ltd. Use of this source code is governed by the Apache 2.0 license. + */ + +package dev.gitlive.firebase.auth + +import cocoapods.FirebaseAuth.* +import platform.Foundation.NSURL + +actual class FirebaseUser internal constructor(val ios: FIRUser) { + actual val uid: String + get() = ios.uid + actual val displayName: String? + get() = ios.displayName + actual val email: String? + get() = ios.email + actual val phoneNumber: String? + get() = ios.phoneNumber + actual val photoURL: String? + get() = ios.photoURL?.absoluteString + actual val isAnonymous: Boolean + get() = ios.anonymous + actual val isEmailVerified: Boolean + get() = ios.emailVerified + actual val metaData: MetaData? + get() = MetaData(ios.metadata) + actual val multiFactor: MultiFactor + get() = MultiFactor(ios.multiFactor) + actual val providerData: List + get() = ios.providerData.mapNotNull { provider -> (provider as? FIRUserInfoProtocol)?.let { UserInfo(it) } } + actual val providerId: String + get() = ios.providerID + actual suspend fun delete() = ios.await { deleteWithCompletion(it) }.run { Unit } + actual suspend fun reload() = ios.await { reloadWithCompletion(it) }.run { Unit } + actual suspend fun getIdToken(forceRefresh: Boolean) { + val token: String = ios.awaitResult { getIDTokenForcingRefresh(forceRefresh, it) } + } + actual suspend fun linkWithCredential(credential: AuthCredential): AuthResult = AuthResult(ios.awaitResult { linkWithCredential(credential.ios, it) }) + actual suspend fun reauthenticate(credential: AuthCredential) { + val result: FIRAuthDataResult = ios.awaitResult { reauthenticateWithCredential(credential.ios, it) } + } + actual suspend fun reauthenticateAndRetrieveData(credential: AuthCredential): AuthResult = AuthResult(ios.awaitResult { reauthenticateAndRetrieveDataWithCredential(credential.ios, it) }) + + actual suspend fun sendEmailVerification(actionCodeSettings: ActionCodeSettings?) = ios.await { + actionCodeSettings?.let { actionSettings -> sendEmailVerificationWithActionCodeSettings(actionSettings.ios, it) } ?: sendEmailVerificationWithCompletion(it) + }.run { Unit } + actual suspend fun unlink(provider: String): FirebaseUser? { + val user: FIRUser? = ios.awaitResult { unlinkFromProvider(provider, it) } + return user?.let { + FirebaseUser(it) + } + } + actual suspend fun updateEmail(email: String) = ios.await { updateEmail(email, it) }.run { Unit } + actual suspend fun updatePassword(password: String) = ios.await { updatePassword(password, it) }.run { Unit } + actual suspend fun updatePhoneNumber(credential: PhoneAuthCredential) = ios.await { updatePhoneNumberCredential(credential.ios, it) }.run { Unit } + actual suspend fun updateProfile(buildRequest: (UserProfileChangeRequest.Builder) -> Unit) { + val request = UserProfileChangeRequest.Builder(this.ios).apply { buildRequest(this) }.build() + ios.await { request.ios.commitChangesWithCompletion(it) } + } + actual suspend fun verifyBeforeUpdateEmail(newEmail: String, actionCodeSettings: ActionCodeSettings?) = ios.await { + actionCodeSettings?.let { actionSettings -> sendEmailVerificationBeforeUpdatingEmail(newEmail, actionSettings.ios, it) } ?: sendEmailVerificationBeforeUpdatingEmail(newEmail, it) + }.run { Unit } +} + +actual class UserInfo(val ios: FIRUserInfoProtocol) { + actual val displayName: String? + get() = ios.displayName + actual val email: String? + get() = ios.email + actual val phoneNumber: String? + get() = ios.phoneNumber + actual val photoURL: String? + get() = ios.photoURL?.absoluteString + actual val providerId: String + get() = ios.providerID + actual val uid: String + get() = ios.uid +} + +actual class MetaData(val ios: FIRUserMetadata) { + actual val creationTime: Long? + get() = ios.creationDate?.timeIntervalSinceReferenceDate?.toLong() + actual val lastSignInTime: Long? + get() = ios.lastSignInDate?.timeIntervalSinceReferenceDate?.toLong() +} + +actual class UserProfileChangeRequest(val ios: FIRUserProfileChangeRequest) { + actual class Builder(private val user: FIRUser) { + + private val request = user.profileChangeRequest() + + actual fun setDisplayName(displayName: String?): Builder = apply { + request.setDisplayName(displayName) + } + actual fun setPhotoURL(photoURL: String?): Builder = apply { + request.setPhotoURL(photoURL?.let { NSURL.URLWithString(it) }) + } + actual fun build(): UserProfileChangeRequest = UserProfileChangeRequest(request) + } + actual val displayName: String? + get() = ios.displayName + actual val photoURL: String? + get() = ios.photoURL?.absoluteString +} From 6abae5bfbc3ae3307430de013e484ac9d8f18f44 Mon Sep 17 00:00:00 2001 From: Gijs van Veen Date: Wed, 12 Aug 2020 23:42:13 +0200 Subject: [PATCH 05/32] Trying to resolve Firestore issues --- build.gradle.kts | 28 ++++++------ firebase-app/build.gradle.kts | 8 +++- .../src/iosMain/c_interop/FirebaseCore.def | 2 +- firebase-auth/build.gradle.kts | 14 ++++-- firebase-common/build.gradle.kts | 2 +- firebase-database/build.gradle.kts | 6 ++- firebase-firestore/build.gradle.kts | 10 +++-- .../gitlive/firebase/firestore/firestore.kt | 43 +++++++++---------- firebase-functions/build.gradle.kts | 6 ++- gradle/wrapper/gradle-wrapper.properties | 2 +- 10 files changed, 68 insertions(+), 53 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 2009426dc..7fa5cad10 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -19,7 +19,7 @@ buildscript { } } dependencies { - classpath("com.android.tools.build:gradle:3.6.1") + classpath("com.android.tools.build:gradle:4.0.1") classpath("de.undercouch:gradle-download-task:4.0.4") classpath("com.adarshr:gradle-test-logger-plugin:2.0.0") } @@ -31,8 +31,8 @@ val minSdkVersion by extra(16) tasks { val downloadIOSFirebaseZipFile by creating(Download::class) { - src("https://github.com/firebase/firebase-ios-sdk/releases/download/6.17.0/Firebase-6.17.0.zip") - dest(File(buildDir, "Firebase-6.17.0.zip")) + src("https://github.com/firebase/firebase-ios-sdk/releases/download/CocoaPods-6.30.0/Firebase.zip") + dest(File(buildDir, "Firebase-6.30.0.zip")) if (System.getenv("token") != null) { username(System.getenv("token")) } @@ -41,7 +41,7 @@ tasks { val unzipIOSFirebase by creating(Copy::class) { if (!File("$buildDir/Firebase").exists()) { - val zipFile = File(buildDir, "Firebase-6.17.0.zip") + val zipFile = File(buildDir, "Firebase-6.30.0.zip") if (!zipFile.exists()) { dependsOn(downloadIOSFirebaseZipFile) } @@ -172,24 +172,24 @@ subprojects { dependencies { "commonMainImplementation"(kotlin("stdlib-common")) - "commonMainImplementation"("org.jetbrains.kotlinx:kotlinx-coroutines-core-common:1.3.6") + "commonMainImplementation"("org.jetbrains.kotlinx:kotlinx-coroutines-core-common:1.3.8") "jsMainImplementation"(kotlin("stdlib-js")) - "jsMainImplementation"("org.jetbrains.kotlinx:kotlinx-coroutines-core-js:1.3.6") - "androidMainImplementation"("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.6") + "jsMainImplementation"("org.jetbrains.kotlinx:kotlinx-coroutines-core-js:1.3.8") + "androidMainImplementation"("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.8") "androidMainImplementation"("org.jetbrains.kotlinx:kotlinx-coroutines-play-services:1.3.6") - "iosMainImplementation"("org.jetbrains.kotlinx:kotlinx-coroutines-core-common:1.3.6") - "iosMainImplementation"("org.jetbrains.kotlinx:kotlinx-coroutines-core-native:1.3.6") + "iosMainImplementation"("org.jetbrains.kotlinx:kotlinx-coroutines-core-common:1.3.8") + "iosMainImplementation"("org.jetbrains.kotlinx:kotlinx-coroutines-core-native:1.3.8") "commonTestImplementation"(kotlin("test-common")) "commonTestImplementation"(kotlin("test-annotations-common")) - "commonTestImplementation"("org.jetbrains.kotlinx:kotlinx-coroutines-core-common:1.3.6") - "commonTestImplementation"("org.jetbrains.kotlinx:kotlinx-coroutines-test:1.3.6") + "commonTestImplementation"("org.jetbrains.kotlinx:kotlinx-coroutines-core-common:1.3.8") + "commonTestImplementation"("org.jetbrains.kotlinx:kotlinx-coroutines-test:1.3.8") "jsTestImplementation"(kotlin("test-js")) "androidAndroidTestImplementation"(kotlin("test-junit")) - "androidAndroidTestImplementation"("junit:junit:4.12") + "androidAndroidTestImplementation"("junit:junit:4.13") "androidAndroidTestImplementation"("androidx.test:core:1.2.0") - "androidAndroidTestImplementation"("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.6") + "androidAndroidTestImplementation"("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.8") "androidAndroidTestImplementation"("androidx.test.ext:junit:1.1.1") - "androidAndroidTestImplementation"("androidx.test:runner:1.1.0") + "androidAndroidTestImplementation"("androidx.test:runner:1.2.0") } } diff --git a/firebase-app/build.gradle.kts b/firebase-app/build.gradle.kts index 5c052146b..f97b2807b 100644 --- a/firebase-app/build.gradle.kts +++ b/firebase-app/build.gradle.kts @@ -67,7 +67,9 @@ kotlin { val iosX64 = iosX64("ios") { binaries { getTest("DEBUG").apply { - linkerOpts("-F${rootProject.buildDir}/Firebase/FirebaseAnalytics") + linkerOpts("-F${rootProject.buildDir}/Firebase/FirebaseAnalytics/FirebaseCore.xcframework/ios-armv7_arm64", + "-F${rootProject.buildDir}/Firebase/FirebaseAnalytics/FirebaseCore.xcframework/ios-i386_x86_64-simulator", + "-F${rootProject.buildDir}/Firebase/FirebaseAnalytics/FirebaseCore.xcframework/ios-x86_64-maccatalyst") linkerOpts("-ObjC") } } @@ -97,7 +99,9 @@ kotlin { val firebasecore by cinterops.creating { packageName("cocoapods.FirebaseCore") defFile(file("$projectDir/src/iosMain/c_interop/FirebaseCore.def")) - compilerOpts("-F${rootProject.buildDir}/Firebase/FirebaseAnalytics") + compilerOpts("-F${rootProject.buildDir}/Firebase/FirebaseAnalytics/FirebaseCore.xcframework/ios-armv7_arm64", + "-F${rootProject.buildDir}/Firebase/FirebaseAnalytics/FirebaseCore.xcframework/ios-i386_x86_64-simulator", + "-F${rootProject.buildDir}/Firebase/FirebaseAnalytics/FirebaseCore.xcframework/ios-x86_64-maccatalyst") } } } diff --git a/firebase-app/src/iosMain/c_interop/FirebaseCore.def b/firebase-app/src/iosMain/c_interop/FirebaseCore.def index cbdfef176..8a7ad7e6a 100644 --- a/firebase-app/src/iosMain/c_interop/FirebaseCore.def +++ b/firebase-app/src/iosMain/c_interop/FirebaseCore.def @@ -1,4 +1,4 @@ language = Objective-C modules = FirebaseCore compilerOpts = -framework FirebaseCore -linkerOpts = -framework FirebaseCore -framework abseil -framework gRPC-Core -framework gRPC-C++ -framework BoringSSL-GRPC -framework leveldb-library -framework GoogleUtilities -framework SystemConfiguration -framework FIRAnalyticsConnector -framework FirebaseAnalytics -framework FirebaseCore -framework FirebaseCoreDiagnostics -framework FirebaseInstallations -framework FirebaseInstanceID -framework GoogleAppMeasurement -framework GoogleDataTransport -framework GoogleUtilities -framework PromisesObjC -framework nanopb -framework StoreKit -lsqlite3 +linkerOpts = -framework FirebaseCore -framework abseil -framework gRPC-Core -framework gRPC-C++ -framework BoringSSL-GRPC -framework leveldb-library -framework GoogleUtilities -framework SystemConfiguration -framework FIRAnalyticsConnector -framework FirebaseAnalytics -framework FirebaseCore -framework FirebaseCoreDiagnostics -framework FirebaseInstallations -framework FirebaseInstanceID -framework GoogleAppMeasurement -framework GoogleDataTransport -framework GoogleUtilities -framework GTMSessionFetcher -framework PromisesObjC -framework nanopb -framework StoreKit -lsqlite3 diff --git a/firebase-auth/build.gradle.kts b/firebase-auth/build.gradle.kts index 9a2bd8a82..c98dc3dcf 100644 --- a/firebase-auth/build.gradle.kts +++ b/firebase-auth/build.gradle.kts @@ -76,8 +76,12 @@ kotlin { val iosX64 = iosX64("ios") { binaries { getTest("DEBUG").apply { - linkerOpts("-F${rootProject.buildDir}/Firebase/FirebaseAnalytics") - linkerOpts("-F${rootProject.buildDir}/Firebase/FirebaseAuth") + linkerOpts("-F${rootProject.buildDir}/Firebase/FirebaseAnalytics/FirebaseCore.xcframework/ios-armv7_arm64", + "-F${rootProject.buildDir}/Firebase/FirebaseAnalytics/FirebaseCore.xcframework/ios-i386_x86_64-simulator", + "-F${rootProject.buildDir}/Firebase/FirebaseAnalytics/FirebaseCore.xcframework/ios-x86_64-maccatalyst") + linkerOpts("-F${rootProject.buildDir}/Firebase/FirebaseAuth/FirebaseAuth.xcframework/ios-armv7_arm64", + "-F${rootProject.buildDir}/Firebase/FirebaseAuth/FirebaseAuth.xcframework/ios-i386_x86_64-simulator", + "-F${rootProject.buildDir}/Firebase/FirebaseAuth/FirebaseAuth.xcframework/ios-x86_64-maccatalyst") linkerOpts("-F${rootProject.buildDir}/Firebase/GoogleSignIn") linkerOpts("-ObjC") // compilerOpts("-framework AppAuth") @@ -103,7 +107,7 @@ kotlin { val androidMain by getting { dependencies { - api("com.google.firebase:firebase-auth:19.1.0") + api("com.google.firebase:firebase-auth:19.3.2") } } @@ -113,7 +117,9 @@ kotlin { val firebaseAuth by cinterops.creating { packageName("cocoapods.FirebaseAuth") defFile(file("$projectDir/src/iosMain/c_interop/FirebaseAuth.def")) - compilerOpts("-F$projectDir/../build/Firebase/FirebaseAuth") + compilerOpts("-F${rootProject.buildDir}/Firebase/FirebaseAuth/FirebaseAuth.xcframework/ios-armv7_arm64", + "-F${rootProject.buildDir}/Firebase/FirebaseAuth/FirebaseAuth.xcframework/ios-i386_x86_64-simulator", + "-F${rootProject.buildDir}/Firebase/FirebaseAuth/FirebaseAuth.xcframework/ios-x86_64-maccatalyst") compilerOpts("-F$projectDir/../build/Firebase/GoogleSignIn") } } diff --git a/firebase-common/build.gradle.kts b/firebase-common/build.gradle.kts index edc3c5a8a..e4116af67 100644 --- a/firebase-common/build.gradle.kts +++ b/firebase-common/build.gradle.kts @@ -69,7 +69,7 @@ kotlin { } val androidMain by getting { dependencies { - api("com.google.firebase:firebase-common:19.2.0") + api("com.google.firebase:firebase-common:19.3.0") api("org.jetbrains.kotlinx:kotlinx-serialization-runtime:0.20.0") } } diff --git a/firebase-database/build.gradle.kts b/firebase-database/build.gradle.kts index 09c4a588b..f3419f0b6 100644 --- a/firebase-database/build.gradle.kts +++ b/firebase-database/build.gradle.kts @@ -71,7 +71,7 @@ kotlin { } val androidMain by getting { dependencies { - api("com.google.firebase:firebase-database:17.0.0") + api("com.google.firebase:firebase-database:19.3.1") } } val jsMain by getting {} @@ -83,7 +83,9 @@ kotlin { val firebaseDatabase by cinterops.creating { packageName("cocoapods.FirebaseDatabase") defFile(file("$projectDir/src/iosMain/c_interop/FirebaseDatabase.def")) - compilerOpts("-F${rootProject.buildDir}/Firebase/FirebaseDatabase") + compilerOpts("-F${rootProject.buildDir}/Firebase/FirebaseDatabase/FirebaseDatabase.xcframework/ios-armv7_arm64", + "-F${rootProject.buildDir}/Firebase/FirebaseDatabase/FirebaseDatabase.xcframework/ios-i386_x86_64-simulator", + "-F${rootProject.buildDir}/Firebase/FirebaseDatabase/FirebaseDatabase.xcframework/ios-x86_64-maccatalyst") } } } diff --git a/firebase-firestore/build.gradle.kts b/firebase-firestore/build.gradle.kts index 949057197..3297be269 100644 --- a/firebase-firestore/build.gradle.kts +++ b/firebase-firestore/build.gradle.kts @@ -1,4 +1,4 @@ -version = "0.2.1" +version = "0.2.0" plugins { id("com.android.library") @@ -67,7 +67,7 @@ kotlin { } val androidMain by getting { dependencies { - api("com.google.firebase:firebase-firestore:21.4.3") + api("com.google.firebase:firebase-firestore:21.5.0") implementation("com.android.support:multidex:1.0.3") } } @@ -81,7 +81,11 @@ kotlin { val firebasefirestore by cinterops.creating { packageName("cocoapods.FirebaseFirestore") defFile(file("$projectDir/src/iosMain/c_interop/FirebaseFirestore.def")) - compilerOpts("-F${rootProject.buildDir}/Firebase/FirebaseFirestore") + compilerOpts( + "-F${rootProject.buildDir}/Firebase/FirebaseFirestore/FirebaseFirestore.xcframework/ios-armv7_arm64", + "-F${rootProject.buildDir}/Firebase/FirebaseFirestore/FirebaseFirestore.xcframework/ios-i386_x86_64-simulator", + "-F${rootProject.buildDir}/Firebase/FirebaseFirestore/FirebaseFirestore.xcframework/ios-x86_64-maccatalyst" + ) } } } diff --git a/firebase-firestore/src/iosMain/kotlin/dev/gitlive/firebase/firestore/firestore.kt b/firebase-firestore/src/iosMain/kotlin/dev/gitlive/firebase/firestore/firestore.kt index 59ceb2345..36dc19d8a 100644 --- a/firebase-firestore/src/iosMain/kotlin/dev/gitlive/firebase/firestore/firestore.kt +++ b/firebase-firestore/src/iosMain/kotlin/dev/gitlive/firebase/firestore/firestore.kt @@ -4,6 +4,7 @@ package dev.gitlive.firebase.firestore +import cocoapods.FirebaseCore.FIRApp import cocoapods.FirebaseFirestore.* import kotlinx.cinterop.* import kotlinx.coroutines.CompletableDeferred @@ -22,14 +23,19 @@ import dev.gitlive.firebase.FirebaseException actual val Firebase.firestore get() = FirebaseFirestore(FIRFirestore.firestore()) -actual fun Firebase.firestore(app: FirebaseApp) = - FirebaseFirestore(FIRFirestore.firestoreForApp(app.ios)) +actual fun Firebase.firestore(app: FirebaseApp): FirebaseFirestore { + val firFirestore = FIRFirestore.firestoreForApp(app.ios) + return FirebaseFirestore(firFirestore) +} actual class FirebaseFirestore(val ios: FIRFirestore) { actual fun collection(collectionPath: String) = CollectionReference(ios.collectionWithPath(collectionPath)) - actual fun document(documentPath: String) = DocumentReference(ios.documentWithPath(documentPath)) + actual fun document(documentPath: String): DocumentReference { + val path = ios.documentWithPath(documentPath) + return DocumentReference(path) + } actual fun batch() = WriteBatch(ios.batch()) @@ -134,37 +140,28 @@ actual class DocumentReference(val ios: FIRDocumentReference) { actual val path: String get() = ios.path - actual suspend fun set(data: Any, encodeDefaults: Boolean, merge: Boolean) = - await { ios.setData(encode(data, encodeDefaults)!! as Map, merge, it) } + actual suspend fun set(data: Any, encodeDefaults: Boolean, merge: Boolean) = await { ios.setData(encode(data, encodeDefaults)!! as Map, merge, it) } - actual suspend fun set(data: Any, encodeDefaults: Boolean, vararg mergeFields: String) = - await { ios.setData(encode(data, encodeDefaults)!! as Map, mergeFields.asList(), it) } + actual suspend fun set(data: Any, encodeDefaults: Boolean, vararg mergeFields: String) = await { ios.setData(encode(data, encodeDefaults)!! as Map, mergeFields.asList(), it) } - actual suspend fun set(data: Any, encodeDefaults: Boolean, vararg mergeFieldPaths: FieldPath) = - await { ios.setData(encode(data, encodeDefaults)!! as Map, mergeFieldPaths.asList(), it) } + actual suspend fun set(data: Any, encodeDefaults: Boolean, vararg mergeFieldPaths: FieldPath) = await { ios.setData(encode(data, encodeDefaults)!! as Map, mergeFieldPaths.asList(), it) } - actual suspend fun set(strategy: SerializationStrategy, data: T, encodeDefaults: Boolean, merge: Boolean) = - await { ios.setData(encode(strategy, data, encodeDefaults)!! as Map, merge, it) } + actual suspend fun set(strategy: SerializationStrategy, data: T, encodeDefaults: Boolean, merge: Boolean) = await { ios.setData(encode(strategy, data, encodeDefaults)!! as Map, merge, it) } - actual suspend fun set(strategy: SerializationStrategy, data: T, encodeDefaults: Boolean, vararg mergeFields: String) = - await { ios.setData(encode(strategy, data, encodeDefaults)!! as Map, mergeFields.asList(), it) } + actual suspend fun set(strategy: SerializationStrategy, data: T, encodeDefaults: Boolean, vararg mergeFields: String) = await { + ios.setData(encode(strategy, data, encodeDefaults)!! as Map, mergeFields.asList(), it) } - actual suspend fun set(strategy: SerializationStrategy, data: T, encodeDefaults: Boolean, vararg mergeFieldPaths: FieldPath) = - await { ios.setData(encode(strategy, data, encodeDefaults)!! as Map, mergeFieldPaths.asList(), it) } + actual suspend fun set(strategy: SerializationStrategy, data: T, encodeDefaults: Boolean, vararg mergeFieldPaths: FieldPath) = await { ios.setData(encode(strategy, data, encodeDefaults)!! as Map, mergeFieldPaths.asList(), it) } @Suppress("UNCHECKED_CAST") - actual suspend fun update(data: Any, encodeDefaults: Boolean) = - await { ios.updateData(encode(data, encodeDefaults) as Map, it) } + actual suspend fun update(data: Any, encodeDefaults: Boolean) = await { ios.updateData(encode(data, encodeDefaults) as Map, it) } @Suppress("UNCHECKED_CAST") - actual suspend fun update(strategy: SerializationStrategy, data: T, encodeDefaults: Boolean) = - await { ios.updateData(encode(strategy, data, encodeDefaults) as Map, it) } + actual suspend fun update(strategy: SerializationStrategy, data: T, encodeDefaults: Boolean) = await { ios.updateData(encode(strategy, data, encodeDefaults) as Map, it) } - actual suspend fun update(vararg fieldsAndValues: Pair) = - await { block -> ios.updateData(fieldsAndValues.associate { it }, block) } + actual suspend fun update(vararg fieldsAndValues: Pair) = await { block -> ios.updateData(fieldsAndValues.associate { it }, block) } - actual suspend fun update(vararg fieldsAndValues: Pair) = - await { block -> ios.updateData(fieldsAndValues.associate { it }, block) } + actual suspend fun update(vararg fieldsAndValues: Pair) = await { block -> ios.updateData(fieldsAndValues.associate { it }, block) } actual suspend fun delete() = await { ios.deleteDocumentWithCompletion(it) } diff --git a/firebase-functions/build.gradle.kts b/firebase-functions/build.gradle.kts index 8924bee86..a4385da0e 100644 --- a/firebase-functions/build.gradle.kts +++ b/firebase-functions/build.gradle.kts @@ -65,7 +65,7 @@ kotlin { } val androidMain by getting { dependencies { - api("com.google.firebase:firebase-functions:19.0.1") + api("com.google.firebase:firebase-functions:19.0.2") } } val iosMain by getting {} @@ -77,7 +77,9 @@ kotlin { val firebasefunctions by cinterops.creating { packageName("cocoapods.FirebaseFunctions") defFile(file("$projectDir/src/iosMain/c_interop/FirebaseFunctions.def")) - compilerOpts("-F${rootProject.buildDir}/Firebase/FirebaseFunctions") + compilerOpts("-F${rootProject.buildDir}/Firebase/FirebaseFunctions/FirebaseFunctions.xcframework/ios-armv7_arm64", + "-F${rootProject.buildDir}/Firebase/FirebaseFunctions/FirebaseFunctions.xcframework/ios-i386_x86_64-simulator", + "-F${rootProject.buildDir}/Firebase/FirebaseFunctions/FirebaseFunctions.xcframework/ios-x86_64-maccatalyst") } } } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index a23876d58..b62e103ed 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.4-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.5.1-all.zip From aabd62b3a0cc3a7b65cf5ab27362b4a04d3057b9 Mon Sep 17 00:00:00 2001 From: Gijs van Veen Date: Fri, 14 Aug 2020 13:09:34 +0200 Subject: [PATCH 06/32] Added iOS methods --- .../dev/gitlive/firebase/auth/credentials.kt | 57 ++++++++++++++-- .../dev/gitlive/firebase/auth/multifactor.kt | 8 +++ .../dev/gitlive/firebase/auth/credentials.kt | 7 +- .../dev/gitlive/firebase/auth/multifactor.kt | 8 +++ .../kotlin/dev/gitlive/firebase/auth/auth.kt | 3 + .../dev/gitlive/firebase/auth/credentials.kt | 66 +++++++++++++++++++ .../dev/gitlive/firebase/auth/multifactor.kt | 13 ++-- 7 files changed, 148 insertions(+), 14 deletions(-) diff --git a/firebase-auth/src/androidMain/kotlin/dev/gitlive/firebase/auth/credentials.kt b/firebase-auth/src/androidMain/kotlin/dev/gitlive/firebase/auth/credentials.kt index a47b14d88..c2a2aa446 100644 --- a/firebase-auth/src/androidMain/kotlin/dev/gitlive/firebase/auth/credentials.kt +++ b/firebase-auth/src/androidMain/kotlin/dev/gitlive/firebase/auth/credentials.kt @@ -5,7 +5,13 @@ package dev.gitlive.firebase.auth import android.app.Activity +import com.google.firebase.FirebaseException +import com.google.firebase.auth.PhoneAuthProvider +import kotlinx.coroutines.CompletableDeferred +import kotlinx.coroutines.coroutineScope +import kotlinx.coroutines.launch import kotlinx.coroutines.tasks.await +import java.util.concurrent.TimeUnit actual open class AuthCredential(open val android: com.google.firebase.auth.AuthCredential) { actual val providerId: String @@ -79,16 +85,55 @@ actual typealias SignInProvider = Activity actual class PhoneAuthProvider(val android: com.google.firebase.auth.PhoneAuthProvider) { - actual companion object { - actual fun credentialWithVerificationIdAndSmsCode(verificationId: String, smsCode: String): PhoneAuthCredential = PhoneAuthCredential(com.google.firebase.auth.PhoneAuthProvider.getCredential(verificationId, smsCode)) - } actual constructor(auth: FirebaseAuth) : this(com.google.firebase.auth.PhoneAuthProvider.getInstance(auth.android)) - fun test() { + actual fun credentialWithVerificationIdAndSmsCode(verificationId: String, smsCode: String): PhoneAuthCredential = PhoneAuthCredential(com.google.firebase.auth.PhoneAuthProvider.getCredential(verificationId, smsCode)) + actual suspend fun verifyPhoneNumber(phoneNumber: String, verificationProvider: PhoneVerificationProvider): AuthCredential = coroutineScope { + val response = CompletableDeferred>() + val callback = object : + PhoneAuthProvider.OnVerificationStateChangedCallbacks() { + + override fun onCodeSent(verificationId: String, forceResending: PhoneAuthProvider.ForceResendingToken) { + verificationProvider.codeSent { android.verifyPhoneNumber(phoneNumber, verificationProvider.timeout, verificationProvider.unit, verificationProvider.activity, this, forceResending) } + } + + override fun onCodeAutoRetrievalTimeOut(verificationId: String) { + launch { + val code = verificationProvider.getVerificationCode() + try { + val credentials = + credentialWithVerificationIdAndSmsCode(verificationId, code) + response.complete(Result.success(credentials)) + } catch (e: Exception) { + response.complete(Result.failure(e)) + } + } + } + + override fun onVerificationCompleted(credential: com.google.firebase.auth.PhoneAuthCredential) { + response.complete(Result.success(AuthCredential(credential))) + } + + override fun onVerificationFailed(error: FirebaseException) { + response.complete(Result.failure(error)) + } + + } + android.verifyPhoneNumber(phoneNumber, verificationProvider.timeout, verificationProvider.unit, verificationProvider.activity, callback) + + response.await().getOrThrow() } } -expect object TwitterAuthProvider { - fun credentialWithTokenAndSecret(token: String, secret: String): AuthCredential +actual interface PhoneVerificationProvider { + val activity: Activity + val timeout: Long + val unit: TimeUnit + fun codeSent(triggerResend: (Unit) -> Unit) + suspend fun getVerificationCode(): String +} + +actual object TwitterAuthProvider { + actual fun credentialWithTokenAndSecret(token: String, secret: String): AuthCredential = AuthCredential(com.google.firebase.auth.TwitterAuthProvider.getCredential(token, secret)) } diff --git a/firebase-auth/src/androidMain/kotlin/dev/gitlive/firebase/auth/multifactor.kt b/firebase-auth/src/androidMain/kotlin/dev/gitlive/firebase/auth/multifactor.kt index 2b553adf5..7721cc175 100644 --- a/firebase-auth/src/androidMain/kotlin/dev/gitlive/firebase/auth/multifactor.kt +++ b/firebase-auth/src/androidMain/kotlin/dev/gitlive/firebase/auth/multifactor.kt @@ -32,3 +32,11 @@ actual class MultiFactorAssertion(val android: com.google.firebase.auth.MultiFac } actual class MultiFactorSession(val android: com.google.firebase.auth.MultiFactorSession) + +actual class MultiFactorResolver(val android: com.google.firebase.auth.MultiFactorResolver) { + actual val auth: FirebaseAuth = FirebaseAuth(android.firebaseAuth) + actual val hints: List = android.hints.map { MultiFactorInfo(it) } + actual val session: MultiFactorSession = MultiFactorSession(android.session) + + actual suspend fun resolveSignIn(assertion: MultiFactorAssertion): AuthResult = AuthResult(android.resolveSignIn(assertion.android).await()) +} \ No newline at end of file diff --git a/firebase-auth/src/commonMain/kotlin/dev/gitlive/firebase/auth/credentials.kt b/firebase-auth/src/commonMain/kotlin/dev/gitlive/firebase/auth/credentials.kt index fa841029e..22e795a39 100644 --- a/firebase-auth/src/commonMain/kotlin/dev/gitlive/firebase/auth/credentials.kt +++ b/firebase-auth/src/commonMain/kotlin/dev/gitlive/firebase/auth/credentials.kt @@ -47,13 +47,12 @@ expect class OAuthProvider constructor(provider: String, auth: FirebaseAuth = Fi expect class SignInProvider expect class PhoneAuthProvider constructor(auth: FirebaseAuth = Firebase.auth) { - companion object { - fun credentialWithVerificationIdAndSmsCode(verificationId: String, smsCode: String): PhoneAuthCredential - } + fun credentialWithVerificationIdAndSmsCode(verificationId: String, smsCode: String): PhoneAuthCredential + suspend fun verifyPhoneNumber(phoneNumber: String, verificationProvider: PhoneVerificationProvider): AuthCredential } -expect class PhoneVerificationProvider +expect interface PhoneVerificationProvider expect object TwitterAuthProvider { fun credentialWithTokenAndSecret(token: String, secret: String): AuthCredential diff --git a/firebase-auth/src/commonMain/kotlin/dev/gitlive/firebase/auth/multifactor.kt b/firebase-auth/src/commonMain/kotlin/dev/gitlive/firebase/auth/multifactor.kt index 7b21e0b23..487fd8124 100644 --- a/firebase-auth/src/commonMain/kotlin/dev/gitlive/firebase/auth/multifactor.kt +++ b/firebase-auth/src/commonMain/kotlin/dev/gitlive/firebase/auth/multifactor.kt @@ -24,3 +24,11 @@ expect class MultiFactorAssertion { } expect class MultiFactorSession + +expect class MultiFactorResolver { + val auth: FirebaseAuth + val hints: List + val session: MultiFactorSession + + suspend fun resolveSignIn(assertion: MultiFactorAssertion): AuthResult +} \ No newline at end of file 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 b97a435b0..5f28533cc 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 @@ -192,6 +192,9 @@ private fun NSError.toException() = when(domain) { FIRAuthErrorCodeInvalidEmail, FIRAuthErrorCodeEmailAlreadyInUse -> FirebaseAuthEmailException(toString()) + FIRAuthErrorCodeCaptchaCheckFailed, + FIRAuthErrorCodeInvalidPhoneNumber, + FIRAuthErrorCodeMissingPhoneNumber, FIRAuthErrorCodeInvalidCredential -> FirebaseAuthInvalidCredentialsException(toString()) FIRAuthErrorCodeInvalidUserToken -> FirebaseAuthInvalidUserException(toString()) diff --git a/firebase-auth/src/iosMain/kotlin/dev/gitlive/firebase/auth/credentials.kt b/firebase-auth/src/iosMain/kotlin/dev/gitlive/firebase/auth/credentials.kt index 2b3135055..88249bc74 100644 --- a/firebase-auth/src/iosMain/kotlin/dev/gitlive/firebase/auth/credentials.kt +++ b/firebase-auth/src/iosMain/kotlin/dev/gitlive/firebase/auth/credentials.kt @@ -24,4 +24,70 @@ actual object EmailAuthProvider { actual object FacebookAuthProvider { actual fun credentialWithAccessToken(accessToken: String): AuthCredential = AuthCredential(FIRFacebookAuthProvider.credentialWithAccessToken(accessToken)) +} + +actual object GithubAuthProvider { + actual fun credentialWithToken(token: String): AuthCredential = AuthCredential(FIRGitHubAuthProvider.credentialWithToken(token)) +} + +actual object GoogleAuthProvider { + actual fun credentialWithIDAndAccessToken(idToken: String, accessToken: String): AuthCredential = AuthCredential(FIRGoogleAuthProvider.credentialWithIDToken(idToken, accessToken)) +} + +actual class OAuthProvider(val ios: FIROAuthProvider, private val auth: FirebaseAuth) { + actual constructor(provider: String, auth: FirebaseAuth) : this(FIROAuthProvider.providerWithProviderID(provider, auth.ios), auth) + + actual companion object { + actual fun credentialsWithAccessToken(providerId: String, accessToken: String): AuthCredential = AuthCredential(FIROAuthProvider.credentialWithProviderID(providerId, accessToken)) + actual fun credentialsWithIDAndAccessToken(providerId: String, idToken: String, accessToken: String): AuthCredential = AuthCredential(FIROAuthProvider.credentialWithProviderID(providerID = providerId, IDToken = idToken, accessToken = accessToken)) + actual fun credentialsWithIDRawNonceAndAccessToken(providerId: String, idToken: String, rawNonce: String, accessToken: String): AuthCredential = AuthCredential(FIROAuthProvider.credentialWithProviderID(providerID = providerId, IDToken = idToken, rawNonce = rawNonce, accessToken = accessToken)) + actual fun credentialsWithIDAndRawNonce(providerId: String, idToken: String, rawNonce: String): AuthCredential = AuthCredential(FIROAuthProvider.credentialWithProviderID(providerID = providerId, IDToken = idToken, rawNonce = rawNonce)) + } + + actual fun addScope(vararg scope: String) { + val scopes = ios.scopes?.mapNotNull { it as? String } ?: emptyList() + ios.setScopes(scopes + scope.asList()) + } + actual fun addCustomParameter(key: String, value: String) { + ios.setCustomParameters(getCustomParameters() + (key to value)) + } + actual fun addCustomParameters(parameters: Map) { + ios.setCustomParameters(getCustomParameters() + parameters) + } + + private fun getCustomParameters(): Map { + val customParameters = ios.customParameters ?: emptyMap() + return customParameters.mapNotNull { + val key = it.key + val value = it.value + if (key is String && value is String) + key to value + else + null}.toMap() + } + + actual suspend fun signIn(signInProvider: SignInProvider): AuthResult = AuthResult(ios.awaitResult { auth.ios.signInWithProvider(ios, signInProvider.delegate, it) }) +} + +actual class SignInProvider(val delegate: FIRAuthUIDelegateProtocol) + +actual class PhoneAuthProvider(val ios: FIRPhoneAuthProvider) { + + actual constructor(auth: FirebaseAuth) : this(FIRPhoneAuthProvider.providerWithAuth(auth.ios)) + + actual fun credentialWithVerificationIdAndSmsCode(verificationId: String, smsCode: String): PhoneAuthCredential = PhoneAuthCredential(ios.credentialWithVerificationID(verificationId, smsCode)) + actual suspend fun verifyPhoneNumber(phoneNumber: String, verificationProvider: PhoneVerificationProvider): AuthCredential { + val verificationId: String = ios.awaitResult { ios.verifyPhoneNumber(phoneNumber, verificationProvider.delegate, it) } + val verificationCode = verificationProvider.getVerificationCode() + return credentialWithVerificationIdAndSmsCode(verificationId, verificationCode) + } +} + +actual interface PhoneVerificationProvider { + val delegate: FIRAuthUIDelegateProtocol + suspend fun getVerificationCode(): String +} + +actual object TwitterAuthProvider { + actual fun credentialWithTokenAndSecret(token: String, secret: String): AuthCredential = AuthCredential(FIRTwitterAuthProvider.credentialWithToken(token, secret)) } \ No newline at end of file diff --git a/firebase-auth/src/iosMain/kotlin/dev/gitlive/firebase/auth/multifactor.kt b/firebase-auth/src/iosMain/kotlin/dev/gitlive/firebase/auth/multifactor.kt index 1c1c2a7f6..757732511 100644 --- a/firebase-auth/src/iosMain/kotlin/dev/gitlive/firebase/auth/multifactor.kt +++ b/firebase-auth/src/iosMain/kotlin/dev/gitlive/firebase/auth/multifactor.kt @@ -4,10 +4,7 @@ package dev.gitlive.firebase.auth -import cocoapods.FirebaseAuth.FIRMultiFactor -import cocoapods.FirebaseAuth.FIRMultiFactorAssertion -import cocoapods.FirebaseAuth.FIRMultiFactorInfo -import cocoapods.FirebaseAuth.FIRMultiFactorSession +import cocoapods.FirebaseAuth.* actual class MultiFactor(val ios: FIRMultiFactor) { actual val enrolledFactors: List @@ -35,3 +32,11 @@ actual class MultiFactorAssertion(val ios: FIRMultiFactorAssertion) { } actual class MultiFactorSession(val ios: FIRMultiFactorSession) + +actual class MultiFactorResolver(val ios: FIRMultiFactorResolver) { + actual val auth: FirebaseAuth = FirebaseAuth(ios.auth) + actual val hints: List = ios.hints.mapNotNull { hint -> (hint as? FIRMultiFactorInfo)?.let { MultiFactorInfo(it) } } + actual val session: MultiFactorSession = MultiFactorSession(ios.session) + + actual suspend fun resolveSignIn(assertion: MultiFactorAssertion): AuthResult = AuthResult(ios.awaitResult { resolveSignInWithAssertion(assertion.ios, it) }) +} \ No newline at end of file From 1226c1c5dc2db840dbf1497f928bd469f35bfc54 Mon Sep 17 00:00:00 2001 From: Gijs van Veen Date: Tue, 18 Aug 2020 12:09:22 +0200 Subject: [PATCH 07/32] Add Javascript --- .../kotlin/dev/gitlive/firebase/auth/auth.kt | 5 +- .../dev/gitlive/firebase/auth/credentials.kt | 11 +- .../kotlin/dev/gitlive/firebase/auth/user.kt | 2 +- .../kotlin/dev/gitlive/firebase/auth/auth.kt | 3 +- .../dev/gitlive/firebase/auth/credentials.kt | 3 +- .../kotlin/dev/gitlive/firebase/auth/user.kt | 2 +- .../kotlin/dev/gitlive/firebase/auth/auth.kt | 15 +- .../dev/gitlive/firebase/auth/credentials.kt | 7 +- .../kotlin/dev/gitlive/firebase/auth/user.kt | 6 +- .../kotlin/dev/gitlive/firebase/auth/auth.kt | 172 +++++++++++++---- .../dev/gitlive/firebase/auth/credentials.kt | 101 ++++++++++ .../dev/gitlive/firebase/auth/multifactor.kt | 44 +++++ .../kotlin/dev/gitlive/firebase/auth/user.kt | 96 +++++++++ .../kotlin/dev/gitlive/firebase/externals.kt | 182 +++++++++++++++++- 14 files changed, 572 insertions(+), 77 deletions(-) create mode 100644 firebase-auth/src/jsMain/kotlin/dev/gitlive/firebase/auth/credentials.kt create mode 100644 firebase-auth/src/jsMain/kotlin/dev/gitlive/firebase/auth/multifactor.kt create mode 100644 firebase-auth/src/jsMain/kotlin/dev/gitlive/firebase/auth/user.kt 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 d875c03bd..ac143346c 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 @@ -111,8 +111,8 @@ actual class ActionCodeSettings private constructor(val android: com.google.fire actual fun setDynamicLinkDomain(dynamicLinkDomain: String): Builder = apply { android.setDynamicLinkDomain(dynamicLinkDomain) } - actual fun setHandleCodeInApp(status: Boolean): Builder = apply { - android.setHandleCodeInApp(status) + actual fun setHandleCodeInApp(canHandleCodeInApp: Boolean): Builder = apply { + android.setHandleCodeInApp(canHandleCodeInApp) } actual fun setIOSBundleId(iOSBundleId: String): Builder = apply { android.setIOSBundleId(iOSBundleId) @@ -145,5 +145,4 @@ actual typealias FirebaseAuthInvalidUserException = com.google.firebase.auth.Fir actual typealias FirebaseAuthMultiFactorException = com.google.firebase.auth.FirebaseAuthMultiFactorException actual typealias FirebaseAuthRecentLoginRequiredException = com.google.firebase.auth.FirebaseAuthRecentLoginRequiredException actual typealias FirebaseAuthUserCollisionException = com.google.firebase.auth.FirebaseAuthUserCollisionException -actual typealias FirebaseAuthWeakPasswordException = com.google.firebase.auth.FirebaseAuthWeakPasswordException actual typealias FirebaseAuthWebException = com.google.firebase.auth.FirebaseAuthWebException diff --git a/firebase-auth/src/androidMain/kotlin/dev/gitlive/firebase/auth/credentials.kt b/firebase-auth/src/androidMain/kotlin/dev/gitlive/firebase/auth/credentials.kt index c2a2aa446..7da683b4c 100644 --- a/firebase-auth/src/androidMain/kotlin/dev/gitlive/firebase/auth/credentials.kt +++ b/firebase-auth/src/androidMain/kotlin/dev/gitlive/firebase/auth/credentials.kt @@ -68,17 +68,16 @@ actual class OAuthProvider(val android: com.google.firebase.auth.OAuthProvider.B } } + private var customParameters: Map = emptyMap() + actual fun addScope(vararg scope: String) { android.scopes = android.scopes + scope.asList() } - actual fun addCustomParameter(key: String, value: String) { - android.addCustomParameter(key, value) - } - actual fun addCustomParameters(parameters: Map) { - android.addCustomParameters(parameters) + actual fun setCustomParameters(parameters: Map) { + customParameters = parameters } - actual suspend fun signIn(signInProvider: SignInProvider): AuthResult = AuthResult(auth.android.startActivityForSignInWithProvider(signInProvider, android.build()).await()) + actual suspend fun signIn(signInProvider: SignInProvider): AuthResult = AuthResult(auth.android.startActivityForSignInWithProvider(signInProvider, android.apply { addCustomParameters(customParameters) }.build()).await()) } actual typealias SignInProvider = Activity diff --git a/firebase-auth/src/androidMain/kotlin/dev/gitlive/firebase/auth/user.kt b/firebase-auth/src/androidMain/kotlin/dev/gitlive/firebase/auth/user.kt index f211e6872..555665c95 100644 --- a/firebase-auth/src/androidMain/kotlin/dev/gitlive/firebase/auth/user.kt +++ b/firebase-auth/src/androidMain/kotlin/dev/gitlive/firebase/auth/user.kt @@ -32,7 +32,7 @@ actual class FirebaseUser internal constructor(val android: com.google.firebase. get() = android.providerId actual suspend fun delete() = android.delete().await().run { Unit } actual suspend fun reload() = android.reload().await().run { Unit } - actual suspend fun getIdToken(forceRefresh: Boolean) = android.getIdToken(forceRefresh).await().run { Unit } + actual suspend fun getIdToken(forceRefresh: Boolean) = android.getIdToken(forceRefresh).await().token actual suspend fun linkWithCredential(credential: AuthCredential): AuthResult = AuthResult(android.linkWithCredential(credential.android).await()) actual suspend fun reauthenticate(credential: AuthCredential) = android.reauthenticate(credential.android).await().run { Unit } actual suspend fun reauthenticateAndRetrieveData(credential: AuthCredential): AuthResult = AuthResult(android.reauthenticateAndRetrieveData(credential.android).await()) 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 5bc9014ba..7414b0845 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 @@ -69,7 +69,7 @@ expect class ActionCodeSettings { class Builder { fun setAndroidPackageName(androidPackageName: String, installIfNotAvailable: Boolean, minimumVersion: String?): Builder fun setDynamicLinkDomain(dynamicLinkDomain: String): Builder - fun setHandleCodeInApp(status: Boolean): Builder + fun setHandleCodeInApp(canHandleCodeInApp: Boolean): Builder fun setIOSBundleId(iOSBundleId: String): Builder fun setUrl(url: String): Builder fun build(): ActionCodeSettings @@ -91,5 +91,4 @@ expect class FirebaseAuthInvalidUserException : FirebaseAuthException expect class FirebaseAuthMultiFactorException: FirebaseAuthException expect class FirebaseAuthRecentLoginRequiredException : FirebaseAuthException expect class FirebaseAuthUserCollisionException : FirebaseAuthException -expect class FirebaseAuthWeakPasswordException : FirebaseAuthException expect class FirebaseAuthWebException : FirebaseAuthException diff --git a/firebase-auth/src/commonMain/kotlin/dev/gitlive/firebase/auth/credentials.kt b/firebase-auth/src/commonMain/kotlin/dev/gitlive/firebase/auth/credentials.kt index 22e795a39..c0d88a703 100644 --- a/firebase-auth/src/commonMain/kotlin/dev/gitlive/firebase/auth/credentials.kt +++ b/firebase-auth/src/commonMain/kotlin/dev/gitlive/firebase/auth/credentials.kt @@ -38,8 +38,7 @@ expect class OAuthProvider constructor(provider: String, auth: FirebaseAuth = Fi } fun addScope(vararg scope: String) - fun addCustomParameter(key: String, value: String) - fun addCustomParameters(parameters: Map) + fun setCustomParameters(parameters: Map) suspend fun signIn(signInProvider: SignInProvider): AuthResult } diff --git a/firebase-auth/src/commonMain/kotlin/dev/gitlive/firebase/auth/user.kt b/firebase-auth/src/commonMain/kotlin/dev/gitlive/firebase/auth/user.kt index 10bd85a96..7eaf21b34 100644 --- a/firebase-auth/src/commonMain/kotlin/dev/gitlive/firebase/auth/user.kt +++ b/firebase-auth/src/commonMain/kotlin/dev/gitlive/firebase/auth/user.kt @@ -18,7 +18,7 @@ expect class FirebaseUser { val providerId: String suspend fun delete() suspend fun reload() - suspend fun getIdToken(forceRefresh: Boolean) + suspend fun getIdToken(forceRefresh: Boolean): String? suspend fun linkWithCredential(credential: AuthCredential): AuthResult suspend fun reauthenticate(credential: AuthCredential) suspend fun reauthenticateAndRetrieveData(credential: AuthCredential): AuthResult 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 5f28533cc..8822f7854 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 @@ -111,8 +111,8 @@ actual class ActionCodeSettings private constructor(val ios: FIRActionCodeSettin actual fun setDynamicLinkDomain(dynamicLinkDomain: String): Builder = apply { ios.setDynamicLinkDomain(dynamicLinkDomain) } - actual fun setHandleCodeInApp(status: Boolean): Builder = apply { - ios.setHandleCodeInApp(status) + actual fun setHandleCodeInApp(canHandleCodeInApp: Boolean): Builder = apply { + ios.setHandleCodeInApp(canHandleCodeInApp) } actual fun setIOSBundleId(iOSBundleId: String): Builder = apply { ios.setIOSBundleID(iOSBundleId) @@ -145,7 +145,6 @@ actual open class FirebaseAuthInvalidUserException(message: String): FirebaseAut actual open class FirebaseAuthMultiFactorException(message: String): FirebaseAuthException(message) actual open class FirebaseAuthRecentLoginRequiredException(message: String): FirebaseAuthException(message) actual open class FirebaseAuthUserCollisionException(message: String): FirebaseAuthException(message) -actual open class FirebaseAuthWeakPasswordException(message: String): FirebaseAuthException(message) actual open class FirebaseAuthWebException(message: String): FirebaseAuthException(message) internal fun T.throwError(block: T.(errorPointer: CPointer>) -> R): R { @@ -195,20 +194,26 @@ private fun NSError.toException() = when(domain) { FIRAuthErrorCodeCaptchaCheckFailed, FIRAuthErrorCodeInvalidPhoneNumber, FIRAuthErrorCodeMissingPhoneNumber, + FIRAuthErrorCodeInvalidVerificationID, + FIRAuthErrorCodeInvalidVerificationCode, + FIRAuthErrorCodeMissingVerificationID, + FIRAuthErrorCodeMissingVerificationCode, + FIRAuthErrorCodeWeakPassword, FIRAuthErrorCodeInvalidCredential -> FirebaseAuthInvalidCredentialsException(toString()) FIRAuthErrorCodeInvalidUserToken -> FirebaseAuthInvalidUserException(toString()) FIRAuthErrorCodeRequiresRecentLogin -> FirebaseAuthRecentLoginRequiredException(toString()) + FIRAuthErrorCodeSecondFactorAlreadyEnrolled, + FIRAuthErrorCodeSecondFactorRequired, + FIRAuthErrorCodeMaximumSecondFactorCountExceeded, FIRAuthErrorCodeMultiFactorInfoNotFound -> FirebaseAuthMultiFactorException(toString()) FIRAuthErrorCodeEmailAlreadyInUse, FIRAuthErrorCodeAccountExistsWithDifferentCredential, FIRAuthErrorCodeCredentialAlreadyInUse -> FirebaseAuthUserCollisionException(toString()) - FIRAuthErrorCodeWeakPassword -> FirebaseAuthWeakPasswordException(toString()) - FIRAuthErrorCodeWebContextAlreadyPresented, FIRAuthErrorCodeWebContextCancelled, FIRAuthErrorCodeWebInternalError -> FirebaseAuthWebException(toString()) diff --git a/firebase-auth/src/iosMain/kotlin/dev/gitlive/firebase/auth/credentials.kt b/firebase-auth/src/iosMain/kotlin/dev/gitlive/firebase/auth/credentials.kt index 88249bc74..6192c47b0 100644 --- a/firebase-auth/src/iosMain/kotlin/dev/gitlive/firebase/auth/credentials.kt +++ b/firebase-auth/src/iosMain/kotlin/dev/gitlive/firebase/auth/credentials.kt @@ -48,11 +48,8 @@ actual class OAuthProvider(val ios: FIROAuthProvider, private val auth: Firebase val scopes = ios.scopes?.mapNotNull { it as? String } ?: emptyList() ios.setScopes(scopes + scope.asList()) } - actual fun addCustomParameter(key: String, value: String) { - ios.setCustomParameters(getCustomParameters() + (key to value)) - } - actual fun addCustomParameters(parameters: Map) { - ios.setCustomParameters(getCustomParameters() + parameters) + actual fun setCustomParameters(parameters: Map) { + ios.setCustomParameters(emptyMap() + parameters) } private fun getCustomParameters(): Map { diff --git a/firebase-auth/src/iosMain/kotlin/dev/gitlive/firebase/auth/user.kt b/firebase-auth/src/iosMain/kotlin/dev/gitlive/firebase/auth/user.kt index 6adaddda1..bbe86e375 100644 --- a/firebase-auth/src/iosMain/kotlin/dev/gitlive/firebase/auth/user.kt +++ b/firebase-auth/src/iosMain/kotlin/dev/gitlive/firebase/auth/user.kt @@ -32,14 +32,12 @@ actual class FirebaseUser internal constructor(val ios: FIRUser) { get() = ios.providerID actual suspend fun delete() = ios.await { deleteWithCompletion(it) }.run { Unit } actual suspend fun reload() = ios.await { reloadWithCompletion(it) }.run { Unit } - actual suspend fun getIdToken(forceRefresh: Boolean) { - val token: String = ios.awaitResult { getIDTokenForcingRefresh(forceRefresh, it) } - } + actual suspend fun getIdToken(forceRefresh: Boolean): String? = ios.awaitResult { getIDTokenForcingRefresh(forceRefresh, it) } actual suspend fun linkWithCredential(credential: AuthCredential): AuthResult = AuthResult(ios.awaitResult { linkWithCredential(credential.ios, it) }) actual suspend fun reauthenticate(credential: AuthCredential) { val result: FIRAuthDataResult = ios.awaitResult { reauthenticateWithCredential(credential.ios, it) } } - actual suspend fun reauthenticateAndRetrieveData(credential: AuthCredential): AuthResult = AuthResult(ios.awaitResult { reauthenticateAndRetrieveDataWithCredential(credential.ios, it) }) + actual suspend fun reauthenticateAndRetrieveData(credential: AuthCredential): AuthResult = AuthResult(ios.awaitResult { reauthenticateWithCredential(credential.ios, it) }) actual suspend fun sendEmailVerification(actionCodeSettings: ActionCodeSettings?) = ios.await { actionCodeSettings?.let { actionSettings -> sendEmailVerificationWithActionCodeSettings(actionSettings.ios, it) } ?: sendEmailVerificationWithCompletion(it) 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 1164568ac..73121867f 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 @@ -20,14 +20,41 @@ actual class FirebaseAuth internal constructor(val js: firebase.auth.Auth) { actual val currentUser: FirebaseUser? get() = rethrow { js.currentUser?.let { FirebaseUser(it) } } - actual suspend fun sendPasswordResetEmail(email: String) = - rethrow { js.sendPasswordResetEmail(email).await() } + actual val authStateChanged get() = callbackFlow { + val unsubscribe = js.onAuthStateChanged { + offer(it?.let { FirebaseUser(it) }) + } + awaitClose { unsubscribe() } + } - actual suspend fun signInWithEmailAndPassword(email: String, password: String) = - rethrow { AuthResult(js.signInWithEmailAndPassword(email, password).await()) } + actual val idTokenChanged get() = callbackFlow { + val unsubscribe = js.onIdTokenChanged { + offer(it?.let { FirebaseUser(it) }) + } + awaitClose { unsubscribe() } + } + + actual var languageCode: String + get() = js.languageCode ?: "" + set(value) { js.languageCode = value } + + actual suspend fun applyActionCode(code: String) = rethrow { js.applyActionCode(code).await() } + actual suspend fun checkActionCode(code: String): ActionCodeResult = rethrow { ActionCodeResult(js.checkActionCode(code).await()) } + actual suspend fun confirmPasswordReset(code: String, newPassword: String) = rethrow { js.confirmPasswordReset(code, newPassword).await() } actual suspend fun createUserWithEmailAndPassword(email: String, password: String) = - rethrow { AuthResult(js.createUserWithEmailAndPassword(email, password).await()) } + rethrow { AuthResult(js.createUserWithEmailAndPassword(email, password).await()) } + + actual suspend fun fetchSignInMethodsForEmail(email: String): SignInMethodQueryResult = rethrow { SignInMethodQueryResult(js.fetchSignInMethodsForEmail(email).await().asList()) } + + actual suspend fun sendPasswordResetEmail(email: String, actionCodeSettings: ActionCodeSettings?) = + rethrow { js.sendPasswordResetEmail(email, actionCodeSettings?.js).await() } + + actual suspend fun sendSignInLinkToEmail(email: String, actionCodeSettings: ActionCodeSettings) = + rethrow { js.sendSignInLinkToEmail(email, actionCodeSettings.js).await() } + + actual suspend fun signInWithEmailAndPassword(email: String, password: String) = + rethrow { AuthResult(js.signInWithEmailAndPassword(email, password).await()) } actual suspend fun signInWithCustomToken(token: String) = rethrow { AuthResult(js.signInWithCustomToken(token).await()) } @@ -35,42 +62,102 @@ actual class FirebaseAuth internal constructor(val js: firebase.auth.Auth) { actual suspend fun signInAnonymously() = rethrow { AuthResult(js.signInAnonymously().await()) } + actual suspend fun signInWithCredential(authCredential: AuthCredential) = + rethrow { AuthResult(js.signInWithCredential(authCredential.js).await()) } + actual suspend fun signOut() = rethrow { js.signOut().await() } - actual val authStateChanged get() = callbackFlow { - val unsubscribe = js.onAuthStateChanged { - offer(it?.let { FirebaseUser(it) }) + actual suspend fun updateCurrentUser(user: FirebaseUser) = + rethrow { + js.updateCurrentUser(user.js).await() + } + actual suspend fun verifyPasswordResetCode(code: String): String = + rethrow { + js.verifyPasswordResetCode(code).await() } - awaitClose { unsubscribe() } - } - actual suspend fun signInWithCredential(authCredential: AuthCredential) = - rethrow { AuthResult(js.signInWithCredential(authCredential.js).await()) } } -actual class AuthCredential(val js: firebase.auth.AuthCredential) - actual class AuthResult internal constructor(val js: firebase.auth.AuthResult) { actual val user: FirebaseUser? get() = rethrow { js.user?.let { FirebaseUser(it) } } } -actual class FirebaseUser internal constructor(val js: firebase.user.User) { - actual val uid: String - get() = rethrow { js.uid } - actual val displayName: String? - get() = rethrow { js.displayName } - actual val email: String? - get() = rethrow { js.email } - actual val phoneNumber: String? - get() = rethrow { js.phoneNumber } - actual val isAnonymous: Boolean - get() = rethrow { js.isAnonymous } - actual val isEmailVerified: Boolean - get() = dev.gitlive.firebase.auth.rethrow { js.emailVerified } - actual suspend fun delete() = rethrow { js.delete().await() } - actual suspend fun reload() = rethrow { js.reload().await() } - actual suspend fun sendEmailVerification() = rethrow { js.sendEmailVerification().await() } +actual class ActionCodeResult(val js: firebase.auth.ActionCodeInfo) { + actual val operation: Operation + get() = when (js.operation) { + "PASSWORD_RESET" -> Operation.PasswordReset + "VERIFY_EMAIL" -> Operation.VerifyEmail + "RECOVER_EMAIL" -> Operation.RecoverEmail + "EMAIL_SIGNIN" -> Operation.SignInWithEmailLink + "VERIFY_AND_CHANGE_EMAIL" -> Operation.VerifyBeforeChangeEmail + "REVERT_SECOND_FACTOR_ADDITION" -> Operation.RevertSecondFactorAddition + else -> Operation.Error + } + actual fun > getData(type: A): T? = when (type) { + is ActionCodeDataType.Email -> js.data.email + is ActionCodeDataType.PreviousEmail -> js.data.previousEmail + is ActionCodeDataType.MultiFactor -> js.data.multiFactorInfo + else -> null + } as? T +} + +actual class SignInMethodQueryResult(actual val signInMethods: List) + +actual class ActionCodeSettings private constructor(val js: firebase.auth.ActionCodeSettings) { + actual class Builder(private var url: String) { + + private var androidSettings: firebase.auth.AndroidActionCodeSettings? = null + private var dynamicLinkDomain: String? = null + private var handleCodeInApp: Boolean? = null + private var iOS: firebase.auth.iOSActionCodeSettings? = null + + actual fun setAndroidPackageName(androidPackageName: String, installIfNotAvailable: Boolean, minimumVersion: String?): Builder = apply { + androidSettings = object : firebase.auth.AndroidActionCodeSettings { + override val installApp: Boolean get() = installIfNotAvailable + override val minimumVersion: String? get() = minimumVersion + override val packageName: String get() = androidPackageName + + } + } + actual fun setDynamicLinkDomain(dynamicLinkDomain: String): Builder = apply { + this.dynamicLinkDomain = dynamicLinkDomain + } + actual fun setHandleCodeInApp(canHandleCodeInApp: Boolean): Builder = apply { + this.handleCodeInApp = canHandleCodeInApp + } + actual fun setIOSBundleId(iOSBundleId: String): Builder = apply { + iOS = object : firebase.auth.iOSActionCodeSettings { + override val bundleId: String? + get() = iOSBundleId + } + } + actual fun setUrl(url: String): Builder = apply { + this.url = url + } + actual fun build(): ActionCodeSettings { + return ActionCodeSettings(object : firebase.auth.ActionCodeSettings { + override val android: firebase.auth.AndroidActionCodeSettings? = this@Builder.androidSettings + override val dynamicLinkDomain: String? = this@Builder.dynamicLinkDomain + override val handleCodeInApp: Boolean? = this@Builder.handleCodeInApp + override val iOS: firebase.auth.iOSActionCodeSettings? = this@Builder.iOS + override val url: String = this@Builder.url + }) + } + } + + actual val canHandleCodeInApp: Boolean + get() = js.handleCodeInApp ?: false + actual val androidInstallApp: Boolean + get() = js.android?.installApp ?: false + actual val androidMinimumVersion: String? + get() = js.android?.minimumVersion + actual val androidPackageName: String? + get() = js.android?.packageName + actual val iOSBundle: String? + get() = js.iOS?.bundleId + actual val url: String + get() = js.url } actual open class FirebaseAuthException(code: String?, cause: Throwable): FirebaseException(code, cause) @@ -78,13 +165,15 @@ actual open class FirebaseAuthActionCodeException(code: String?, cause: Throwabl actual open class FirebaseAuthEmailException(code: String?, cause: Throwable): FirebaseAuthException(code, cause) actual open class FirebaseAuthInvalidCredentialsException(code: String?, cause: Throwable): FirebaseAuthException(code, cause) actual open class FirebaseAuthInvalidUserException(code: String?, cause: Throwable): FirebaseAuthException(code, cause) +actual open class FirebaseAuthMultiFactorException(code: String?, cause: Throwable): FirebaseAuthException(code, cause) actual open class FirebaseAuthRecentLoginRequiredException(code: String?, cause: Throwable): FirebaseAuthException(code, cause) actual open class FirebaseAuthUserCollisionException(code: String?, cause: Throwable): FirebaseAuthException(code, cause) actual open class FirebaseAuthWebException(code: String?, cause: Throwable): FirebaseAuthException(code, cause) -private inline fun T.rethrow(function: T.() -> R): R = dev.gitlive.firebase.auth.rethrow { function() } -private inline fun rethrow(function: () -> R): R { +internal inline fun T.rethrow(function: T.() -> R): R = dev.gitlive.firebase.auth.rethrow { function() } + +internal inline fun rethrow(function: () -> R): R { try { return function() } catch (e: Exception) { @@ -94,13 +183,23 @@ private inline fun rethrow(function: () -> R): R { } } -private fun errorToException(cause: Throwable) = when(val code = cause.asDynamic().code as String?) { +internal fun errorToException(cause: Throwable) = when(val code = cause.asDynamic().code as String?) { "auth/invalid-user-token" -> FirebaseAuthInvalidUserException(code, cause) "auth/requires-recent-login" -> FirebaseAuthRecentLoginRequiredException(code, cause) "auth/user-disabled" -> FirebaseAuthInvalidUserException(code, cause) "auth/user-token-expired" -> FirebaseAuthInvalidUserException(code, cause) "auth/web-storage-unsupported" -> FirebaseAuthWebException(code, cause) "auth/network-request-failed" -> FirebaseNetworkException(code, cause) + "auth/invalid-credential", + "auth/invalid-verification-code", + "auth/missing-verification-code", + "auth/invalid-verification-id", + "auth/missing-verification-id" -> FirebaseAuthInvalidCredentialsException(code, cause) + "auth/maximum-second-factor-count-exceeded", + "auth/second-factor-already-in-use" -> FirebaseAuthMultiFactorException(code, cause) + "auth/credential-already-in-use" -> FirebaseAuthUserCollisionException(code, cause) + "auth/invalid-email" -> FirebaseAuthEmailException(code, cause) + // "auth/app-deleted" -> // "auth/app-not-authorized" -> // "auth/argument-error" -> @@ -110,10 +209,3 @@ private fun errorToException(cause: Throwable) = when(val code = cause.asDynamic // "auth/unauthorized-domain" -> else -> FirebaseAuthException(code, cause) } - -actual object EmailAuthProvider { - actual fun credentialWithEmail( - email: String, - password: String - ): AuthCredential = AuthCredential(firebase.auth.EmailAuthProvider.credential(email, password)) -} \ No newline at end of file diff --git a/firebase-auth/src/jsMain/kotlin/dev/gitlive/firebase/auth/credentials.kt b/firebase-auth/src/jsMain/kotlin/dev/gitlive/firebase/auth/credentials.kt new file mode 100644 index 000000000..ec79ef921 --- /dev/null +++ b/firebase-auth/src/jsMain/kotlin/dev/gitlive/firebase/auth/credentials.kt @@ -0,0 +1,101 @@ +package dev.gitlive.firebase.auth + +import dev.gitlive.firebase.firebase +import kotlinx.coroutines.await + + +actual open class AuthCredential(val js: firebase.auth.AuthCredential) { + actual val providerId: String + get() = js.providerId +} + +actual class PhoneAuthCredential(js: firebase.auth.AuthCredential) : AuthCredential(js) +actual class OAuthCredential(js: firebase.auth.AuthCredential) : AuthCredential(js) + +actual object EmailAuthProvider { + actual fun credentialWithEmail( + email: String, + password: String + ): AuthCredential = AuthCredential(firebase.auth.EmailAuthProvider.credential(email, password)) +} + +actual object FacebookAuthProvider { + actual fun credentialWithAccessToken(accessToken: String): AuthCredential = AuthCredential(firebase.auth.FacebookAuthProvider.credential(accessToken)) +} + +actual object GithubAuthProvider { + actual fun credentialWithToken(token: String): AuthCredential = AuthCredential(firebase.auth.GithubAuthProvider.credential(token)) +} + +actual object GoogleAuthProvider { + actual fun credentialWithIDAndAccessToken(idToken: String, accessToken: String): AuthCredential = AuthCredential(firebase.auth.GoogleAuthProvider.credential(idToken, accessToken)) +} + +actual class OAuthProvider(val js: firebase.auth.OAuthProvider, private val auth: FirebaseAuth) { + actual constructor(provider: String, auth: FirebaseAuth) : this(firebase.auth.OAuthProvider(provider), auth) + + actual companion object { + actual fun credentialsWithAccessToken(providerId: String, accessToken: String): AuthCredential = getCredentials(providerId, accessToken = accessToken) + actual fun credentialsWithIDAndAccessToken(providerId: String, idToken: String, accessToken: String): AuthCredential = getCredentials(providerId, accessToken = accessToken, idToken = idToken) + actual fun credentialsWithIDRawNonceAndAccessToken(providerId: String, idToken: String, rawNonce: String, accessToken: String): AuthCredential = getCredentials(providerId, accessToken = accessToken, idToken = idToken, rawNonce = rawNonce) + actual fun credentialsWithIDAndRawNonce(providerId: String, idToken: String, rawNonce: String): AuthCredential = getCredentials(providerId, idToken = idToken, rawNonce = rawNonce) + + private fun getCredentials(provider: String, accessToken: String? = null, idToken: String? = null, rawNonce: String? = null): AuthCredential = rethrow { + val acT = accessToken + val idT = idToken + val rno = rawNonce + val provider = firebase.auth.OAuthProvider(provider) + val credentials = provider.credential(object : firebase.auth.OAuthCredentialOptions { + override val accessToken: String? = acT + override val idToken: String? = idT + override val rawNonce: String? = rno + }, accessToken) + return AuthCredential(credentials) + } + } + + actual fun addScope(vararg scope: String) = rethrow { scope.forEach { js.addScope(it) } } + actual fun setCustomParameters(parameters: Map) = rethrow { + js.setCustomParameters(parameters) + } + + actual suspend fun signIn(signInProvider: SignInProvider): AuthResult = rethrow { + AuthResult(when (signInProvider.type) { + SignInProvider.SignInType.Popup -> { + auth.js.signInWithPopup(js).await() + } + SignInProvider.SignInType.Redirect -> { + auth.js.signInWithRedirect(js).await() + auth.js.getRedirectResult().await() + } + }) + } +} + +actual class SignInProvider(val type: SignInType) { + enum class SignInType { + Popup, + Redirect + } +} + +actual class PhoneAuthProvider(val js: firebase.auth.PhoneAuthProvider) { + + actual constructor(auth: FirebaseAuth) : this(firebase.auth.PhoneAuthProvider(auth.js)) + + actual fun credentialWithVerificationIdAndSmsCode(verificationId: String, smsCode: String): PhoneAuthCredential = PhoneAuthCredential(firebase.auth.PhoneAuthProvider.credential(verificationId, smsCode)) + actual suspend fun verifyPhoneNumber(phoneNumber: String, verificationProvider: PhoneVerificationProvider): AuthCredential = rethrow { + val verificationId = js.verifyPhoneNumber(phoneNumber, verificationProvider.verifier).await() + val verificationCode = verificationProvider.getVerificationCode(verificationId) + credentialWithVerificationIdAndSmsCode(verificationId, verificationCode) + } +} + +actual interface PhoneVerificationProvider { + val verifier: firebase.auth.ApplicationVerifier + suspend fun getVerificationCode(verificationId: String): String +} + +actual object TwitterAuthProvider { + actual fun credentialWithTokenAndSecret(token: String, secret: String): AuthCredential = AuthCredential(firebase.auth.TwitterAuthProvider.credential(token, secret)) +} \ No newline at end of file diff --git a/firebase-auth/src/jsMain/kotlin/dev/gitlive/firebase/auth/multifactor.kt b/firebase-auth/src/jsMain/kotlin/dev/gitlive/firebase/auth/multifactor.kt new file mode 100644 index 000000000..1f0a4a534 --- /dev/null +++ b/firebase-auth/src/jsMain/kotlin/dev/gitlive/firebase/auth/multifactor.kt @@ -0,0 +1,44 @@ +package dev.gitlive.firebase.auth + +import dev.gitlive.firebase.firebase +import kotlinx.coroutines.await +import kotlin.js.Date + +actual class MultiFactor(val js: firebase.multifactor.MultiFactorUser) { + actual val enrolledFactors: List + get() = rethrow { js.enrolledFactors.map { MultiFactorInfo(it) } } + actual suspend fun enroll(multiFactorAssertion: MultiFactorAssertion, displayName: String?) = + rethrow { js.enroll(multiFactorAssertion.js, displayName).await() } + actual suspend fun getSession(): MultiFactorSession = + rethrow { MultiFactorSession(js.getSession().await()) } + actual suspend fun unenroll(multiFactorInfo: MultiFactorInfo) = + rethrow { js.unenroll(multiFactorInfo.js).await() } + actual suspend fun unenroll(factorUid: String) = + rethrow { js.unenroll(factorUid).await() } +} + +actual class MultiFactorInfo(val js: firebase.multifactor.MultiFactorInfo) { + actual val displayName: String? + get() = rethrow { js.displayName } + actual val enrollmentTime: Long + get() = rethrow { (Date(js.enrollmentTime).getTime() / 1000.0).toLong() } + actual val factorId: String + get() = rethrow { js.factorId } + actual val uid: String + get() = rethrow { js.uid } +} + +actual class MultiFactorAssertion(val js: firebase.multifactor.MultiFactorAssertion) { + actual val factorId: String + get() = rethrow { js.factorId } +} + +actual class MultiFactorSession(val js: firebase.multifactor.MultiFactorSession) + +actual class MultiFactorResolver(val js: firebase.multifactor.MultifactorResolver) { + actual val auth: FirebaseAuth = rethrow { FirebaseAuth(js.auth) } + actual val hints: List = rethrow { js.hints.map { MultiFactorInfo(it) } } + actual val session: MultiFactorSession = rethrow { MultiFactorSession(js.session) } + + actual suspend fun resolveSignIn(assertion: MultiFactorAssertion): AuthResult = rethrow { AuthResult(js.resolveSignIn(assertion.js).await()) } +} \ No newline at end of file diff --git a/firebase-auth/src/jsMain/kotlin/dev/gitlive/firebase/auth/user.kt b/firebase-auth/src/jsMain/kotlin/dev/gitlive/firebase/auth/user.kt new file mode 100644 index 000000000..31fea5615 --- /dev/null +++ b/firebase-auth/src/jsMain/kotlin/dev/gitlive/firebase/auth/user.kt @@ -0,0 +1,96 @@ +package dev.gitlive.firebase.auth + +import dev.gitlive.firebase.firebase +import kotlinx.coroutines.await +import kotlin.js.Date + +actual class FirebaseUser internal constructor(val js: firebase.user.User) { + actual val uid: String + get() = rethrow { js.uid } + actual val displayName: String? + get() = rethrow { js.displayName } + actual val email: String? + get() = rethrow { js.email } + actual val phoneNumber: String? + get() = rethrow { js.phoneNumber } + actual val photoURL: String? + get() = rethrow { js.photoURL } + actual val isAnonymous: Boolean + get() = rethrow { js.isAnonymous } + actual val isEmailVerified: Boolean + get() = rethrow { js.emailVerified } + actual val metaData: MetaData? + get() = rethrow { MetaData(js.metadata) } + actual val multiFactor: MultiFactor + get() = rethrow { MultiFactor(js.multiFactor) } + actual val providerData: List + get() = rethrow { js.providerData.map { UserInfo(it) } } + actual val providerId: String + get() = rethrow { js.providerId } + actual suspend fun delete() = rethrow { js.delete().await() } + actual suspend fun reload() = rethrow { js.reload().await() } + actual suspend fun getIdToken(forceRefresh: Boolean): String? = rethrow { js.getIdToken(forceRefresh).await() } + actual suspend fun linkWithCredential(credential: AuthCredential): AuthResult = rethrow { AuthResult(js.linkWithCredential(credential.js).await()) } + actual suspend fun reauthenticate(credential: AuthCredential) = rethrow { + js.reauthenticateWithCredential(credential.js).await() + Unit + } + actual suspend fun reauthenticateAndRetrieveData(credential: AuthCredential): AuthResult = rethrow { AuthResult(js.reauthenticateWithCredential(credential.js).await()) } + + actual suspend fun sendEmailVerification(actionCodeSettings: ActionCodeSettings?) = rethrow { js.sendEmailVerification(actionCodeSettings?.js).await() } + actual suspend fun unlink(provider: String): FirebaseUser? = rethrow { FirebaseUser(js.unlink(provider).await()) } + actual suspend fun updateEmail(email: String) = rethrow { js.updateEmail(email).await() } + actual suspend fun updatePassword(password: String) = rethrow { js.updatePassword(password).await() } + actual suspend fun updatePhoneNumber(credential: PhoneAuthCredential) = rethrow { js.updatePhoneNumber(credential.js).await() } + actual suspend fun updateProfile(buildRequest: (UserProfileChangeRequest.Builder) -> Unit) = rethrow { + val request = UserProfileChangeRequest.Builder().apply(buildRequest).build() + js.updateProfile(request.js).await() + } + actual suspend fun verifyBeforeUpdateEmail(newEmail: String, actionCodeSettings: ActionCodeSettings?) = rethrow { js.verifyBeforeUpdateEmail(newEmail, actionCodeSettings?.js).await() } +} + +actual class UserInfo(val js: firebase.user.UserInfo) { + actual val displayName: String? + get() = rethrow { js.displayName } + actual val email: String? + get() = rethrow { js.email } + actual val phoneNumber: String? + get() = rethrow { js.phoneNumber } + actual val photoURL: String? + get() = rethrow { js.photoURL } + actual val providerId: String + get() = rethrow { js.providerId } + actual val uid: String + get() = rethrow { js.uid } +} + +actual class MetaData(val js: firebase.user.UserMetadata) { + actual val creationTime: Long? + get() = rethrow {js.creationTime?.let { (Date(it).getTime() / 1000.0).toLong() } } + actual val lastSignInTime: Long? + get() = rethrow {js.lastSignInTime?.let { (Date(it).getTime() / 1000.0).toLong() } } +} + +actual class UserProfileChangeRequest(val js: firebase.user.ProfileUpdateRequest) { + + actual class Builder { + + private var displayName: String? = null + private var photoURL: String? = null + + actual fun setDisplayName(displayName: String?): Builder = apply { + this.displayName = displayName + } + actual fun setPhotoURL(photoURL: String?): Builder = apply { + this.photoURL = photoURL + } + actual fun build(): UserProfileChangeRequest = UserProfileChangeRequest(object : firebase.user.ProfileUpdateRequest { + override val displayName: String? = this@Builder.displayName + override val photoURL: String? = this@Builder.photoURL + }) + } + actual val displayName: String? + get() = rethrow { js.displayName } + actual val photoURL: String? + get() = rethrow { js.photoURL } +} diff --git a/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals.kt b/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals.kt index bdb82b459..253ff4f81 100644 --- a/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals.kt +++ b/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals.kt @@ -56,29 +56,126 @@ external object firebase { object auth { open class Auth { val currentUser: user.User? + var languageCode: String? - fun sendPasswordResetEmail(email: String): Promise - fun signInWithEmailAndPassword(email: String, password: String): Promise + fun applyActionCode(code: String): Promise + fun checkActionCode(code: String): Promise + fun confirmPasswordReset(code: String, newPassword: String): Promise fun createUserWithEmailAndPassword(email: String, password: String): Promise + fun fetchSignInMethodsForEmail(email: String): Promise> + fun sendPasswordResetEmail(email: String, actionCodeSettings: ActionCodeSettings?): Promise + fun sendSignInLinkToEmail(email: String, actionCodeSettings: ActionCodeSettings?): Promise + fun signInWithEmailAndPassword(email: String, password: String): Promise fun signInWithCustomToken(token: String): Promise fun signInAnonymously(): Promise fun signInWithCredential(authCredential: AuthCredential): Promise + fun signInWithPopup(provider: AuthProvider): Promise + fun signInWithRedirect(provider: AuthProvider): Promise + fun getRedirectResult(): Promise fun signOut(): Promise + fun updateCurrentUser(user: user.User?): Promise + fun verifyPasswordResetCode(code: String): Promise fun onAuthStateChanged(nextOrObserver: (user.User?) -> Unit): () -> Unit + fun onIdTokenChanged(nextOrObserver: (user.User?) -> Unit): () -> Unit } - interface AuthResult { + abstract class AuthResult { + val credential: AuthCredential? + val operationType: String? val user: user.User? } - interface AuthCredential + abstract class AuthCredential { + val providerId: String + val signInMethod: String + } + + abstract class ActionCodeInfo { + val operation: String + val data: ActionCodeData + } + + abstract class ActionCodeData { + val email: String? + val multiFactorInfo: multifactor.MultiFactorInfo? + val previousEmail: String? + } + + interface ActionCodeSettings { + val android: AndroidActionCodeSettings? + val dynamicLinkDomain: String? + val handleCodeInApp: Boolean? + val iOS: iOSActionCodeSettings? + val url: String + } + + interface AndroidActionCodeSettings { + val installApp: Boolean? + val minimumVersion: String? + val packageName: String + } + + interface iOSActionCodeSettings { + val bundleId: String? + } + + interface AuthProvider + + class EmailAuthProvider : AuthProvider { + companion object { + fun credential(email : String, password : String): AuthCredential + } + } + + class FacebookAuthProvider : AuthProvider { + companion object { + fun credential(token: String): AuthCredential + } + } + + class GithubAuthProvider : AuthProvider { + companion object { + fun credential(token: String): AuthCredential + } + } + + class GoogleAuthProvider : AuthProvider{ + companion object { + fun credential(idToken: String?, accessToken: String?): AuthCredential + } + } + + open class OAuthProvider(providerId: String) : AuthProvider { + val providerId: String + fun credential(optionsOrIdToken: OAuthCredentialOptions?, accessToken: String?): AuthCredential + + fun addScope(scope: String) + fun setCustomParameters(customOAuthParameters: Map) + } + + interface OAuthCredentialOptions { + val accessToken: String? + val idToken: String? + val rawNonce: String? + } - abstract class EmailAuthProvider { + class PhoneAuthProvider(auth: Auth?) : AuthProvider { companion object { - fun credential(email : String, password : String) : AuthCredential + fun credential(verificationId: String, verificationCode: String): AuthCredential } + fun verifyPhoneNumber(phoneInfoOptions: String, applicationVerifier: ApplicationVerifier): Promise + } + + abstract class ApplicationVerifier { + val type: String + fun verify(): Promise } + class TwitterAuthProvider : AuthProvider { + companion object { + fun credential (token: String, secret: String): AuthCredential + } + } } fun User(a: Any,b: Any,c: Any): user.User @@ -88,13 +185,82 @@ external object firebase { val uid: String val displayName: String? val email: String? + val emailVerified: Boolean + val metadata: UserMetadata + val multiFactor: multifactor.MultiFactorUser val phoneNumber: String? + val photoURL: String? + val providerData: Array + val providerId: String + val refreshToken: String + val tenantId: String? val isAnonymous: Boolean - val emailVerified: Boolean fun delete(): Promise + fun getIdToken(forceRefresh: Boolean?): Promise + fun linkWithCredential(credential: auth.AuthCredential): Promise + fun reauthenticateWithCredential(credential: auth.AuthCredential): Promise fun reload(): Promise - fun sendEmailVerification(): Promise + fun sendEmailVerification(actionCodeSettings: auth.ActionCodeSettings?): Promise + fun unlink(providerId: String): Promise + fun updateEmail(newEmail: String): Promise + fun updatePassword(newPassword: String): Promise + fun updatePhoneNumber(phoneCredential: auth.AuthCredential): Promise + fun updateProfile(profile: ProfileUpdateRequest): Promise + fun verifyBeforeUpdateEmail(newEmail: String, actionCodeSettings: auth.ActionCodeSettings?): Promise + } + + abstract class UserMetadata { + val creationTime: String? + val lastSignInTime: String? + } + + abstract class UserInfo { + val displayName: String? + val email: String? + val phoneNumber: String? + val photoURL: String? + val providerId: String + val uid: String + } + + interface ProfileUpdateRequest { + val displayName: String? + val photoURL: String? + } + + } + + object multifactor { + abstract class MultiFactorUser { + val enrolledFactors: Array + + fun enroll(assertion: MultiFactorAssertion, displayName: String?): Promise + fun getSession(): Promise + fun unenroll(option: MultiFactorInfo): Promise + fun unenroll(option: String): Promise + } + + abstract class MultiFactorInfo { + val displayName: String? + val enrollmentTime: String + val factorId: String + val uid: String + } + + abstract class MultiFactorAssertion { + val factorId: String + } + + interface MultiFactorSession + + abstract class MultifactorResolver { + + val auth: auth.Auth + val hints: Array + val session: MultiFactorSession + + fun resolveSignIn(assertion: MultiFactorAssertion): Promise } } From f8777aae01826fe3f6eb5d550eed6183e05d52ff Mon Sep 17 00:00:00 2001 From: Gijs van Veen Date: Tue, 18 Aug 2020 17:24:57 +0200 Subject: [PATCH 08/32] Cleaned up .def files Dependencies now part of actual submodules --- firebase-app/src/iosMain/c_interop/FirebaseCore.def | 2 +- .../src/androidMain/kotlin/dev/gitlive/firebase/auth/user.kt | 4 ++-- .../src/commonMain/kotlin/dev/gitlive/firebase/auth/user.kt | 2 +- .../src/iosMain/kotlin/dev/gitlive/firebase/auth/user.kt | 4 ++-- .../src/jsMain/kotlin/dev/gitlive/firebase/auth/user.kt | 2 +- firebase-database/src/iosMain/c_interop/FirebaseDatabase.def | 2 +- .../src/iosMain/c_interop/FirebaseFirestore.def | 2 +- .../src/iosMain/c_interop/FirebaseFunctions.def | 2 +- 8 files changed, 10 insertions(+), 10 deletions(-) diff --git a/firebase-app/src/iosMain/c_interop/FirebaseCore.def b/firebase-app/src/iosMain/c_interop/FirebaseCore.def index 8a7ad7e6a..e2aa4e4aa 100644 --- a/firebase-app/src/iosMain/c_interop/FirebaseCore.def +++ b/firebase-app/src/iosMain/c_interop/FirebaseCore.def @@ -1,4 +1,4 @@ language = Objective-C modules = FirebaseCore compilerOpts = -framework FirebaseCore -linkerOpts = -framework FirebaseCore -framework abseil -framework gRPC-Core -framework gRPC-C++ -framework BoringSSL-GRPC -framework leveldb-library -framework GoogleUtilities -framework SystemConfiguration -framework FIRAnalyticsConnector -framework FirebaseAnalytics -framework FirebaseCore -framework FirebaseCoreDiagnostics -framework FirebaseInstallations -framework FirebaseInstanceID -framework GoogleAppMeasurement -framework GoogleDataTransport -framework GoogleUtilities -framework GTMSessionFetcher -framework PromisesObjC -framework nanopb -framework StoreKit -lsqlite3 +linkerOpts = -framework FirebaseCore -framework FirebaseCoreDiagnostics -framework FirebaseAnalytics -framework FIRAnalyticsConnector -framework GoogleAppMeasurement -framework FirebaseInstallations -framework GoogleDataTransport -framework GoogleUtilities -framework PromisesObjC -framework nanopb diff --git a/firebase-auth/src/androidMain/kotlin/dev/gitlive/firebase/auth/user.kt b/firebase-auth/src/androidMain/kotlin/dev/gitlive/firebase/auth/user.kt index 555665c95..77802efef 100644 --- a/firebase-auth/src/androidMain/kotlin/dev/gitlive/firebase/auth/user.kt +++ b/firebase-auth/src/androidMain/kotlin/dev/gitlive/firebase/auth/user.kt @@ -44,8 +44,8 @@ actual class FirebaseUser internal constructor(val android: com.google.firebase. actual suspend fun updateEmail(email: String) = android.updateEmail(email).await().run { Unit } actual suspend fun updatePassword(password: String) = android.updatePassword(password).await().run { Unit } actual suspend fun updatePhoneNumber(credential: PhoneAuthCredential) = android.updatePhoneNumber(credential.android).await().run { Unit } - actual suspend fun updateProfile(buildRequest: (UserProfileChangeRequest.Builder) -> Unit) { - val request = UserProfileChangeRequest.Builder().apply { buildRequest(this) }.build() + actual suspend fun updateProfile(buildRequest: UserProfileChangeRequest.Builder.() -> Unit) { + val request = UserProfileChangeRequest.Builder().apply(buildRequest).build() android.updateProfile(request.android).await() } actual suspend fun verifyBeforeUpdateEmail(newEmail: String, actionCodeSettings: ActionCodeSettings?) = android.verifyBeforeUpdateEmail(newEmail, actionCodeSettings?.android).await().run { Unit } diff --git a/firebase-auth/src/commonMain/kotlin/dev/gitlive/firebase/auth/user.kt b/firebase-auth/src/commonMain/kotlin/dev/gitlive/firebase/auth/user.kt index 7eaf21b34..7804eb881 100644 --- a/firebase-auth/src/commonMain/kotlin/dev/gitlive/firebase/auth/user.kt +++ b/firebase-auth/src/commonMain/kotlin/dev/gitlive/firebase/auth/user.kt @@ -27,7 +27,7 @@ expect class FirebaseUser { suspend fun updateEmail(email: String) suspend fun updatePassword(password: String) suspend fun updatePhoneNumber(credential: PhoneAuthCredential) - suspend fun updateProfile(buildRequest: (UserProfileChangeRequest.Builder) -> Unit) + suspend fun updateProfile(buildRequest: UserProfileChangeRequest.Builder.() -> Unit) suspend fun verifyBeforeUpdateEmail(newEmail: String, actionCodeSettings: ActionCodeSettings? = null) } diff --git a/firebase-auth/src/iosMain/kotlin/dev/gitlive/firebase/auth/user.kt b/firebase-auth/src/iosMain/kotlin/dev/gitlive/firebase/auth/user.kt index bbe86e375..af83cca4c 100644 --- a/firebase-auth/src/iosMain/kotlin/dev/gitlive/firebase/auth/user.kt +++ b/firebase-auth/src/iosMain/kotlin/dev/gitlive/firebase/auth/user.kt @@ -51,8 +51,8 @@ actual class FirebaseUser internal constructor(val ios: FIRUser) { actual suspend fun updateEmail(email: String) = ios.await { updateEmail(email, it) }.run { Unit } actual suspend fun updatePassword(password: String) = ios.await { updatePassword(password, it) }.run { Unit } actual suspend fun updatePhoneNumber(credential: PhoneAuthCredential) = ios.await { updatePhoneNumberCredential(credential.ios, it) }.run { Unit } - actual suspend fun updateProfile(buildRequest: (UserProfileChangeRequest.Builder) -> Unit) { - val request = UserProfileChangeRequest.Builder(this.ios).apply { buildRequest(this) }.build() + actual suspend fun updateProfile(buildRequest: UserProfileChangeRequest.Builder.() -> Unit) { + val request = UserProfileChangeRequest.Builder(this.ios).apply(buildRequest).build() ios.await { request.ios.commitChangesWithCompletion(it) } } actual suspend fun verifyBeforeUpdateEmail(newEmail: String, actionCodeSettings: ActionCodeSettings?) = ios.await { diff --git a/firebase-auth/src/jsMain/kotlin/dev/gitlive/firebase/auth/user.kt b/firebase-auth/src/jsMain/kotlin/dev/gitlive/firebase/auth/user.kt index 31fea5615..c55848fc5 100644 --- a/firebase-auth/src/jsMain/kotlin/dev/gitlive/firebase/auth/user.kt +++ b/firebase-auth/src/jsMain/kotlin/dev/gitlive/firebase/auth/user.kt @@ -42,7 +42,7 @@ actual class FirebaseUser internal constructor(val js: firebase.user.User) { actual suspend fun updateEmail(email: String) = rethrow { js.updateEmail(email).await() } actual suspend fun updatePassword(password: String) = rethrow { js.updatePassword(password).await() } actual suspend fun updatePhoneNumber(credential: PhoneAuthCredential) = rethrow { js.updatePhoneNumber(credential.js).await() } - actual suspend fun updateProfile(buildRequest: (UserProfileChangeRequest.Builder) -> Unit) = rethrow { + actual suspend fun updateProfile(buildRequest: UserProfileChangeRequest.Builder.() -> Unit) = rethrow { val request = UserProfileChangeRequest.Builder().apply(buildRequest).build() js.updateProfile(request.js).await() } diff --git a/firebase-database/src/iosMain/c_interop/FirebaseDatabase.def b/firebase-database/src/iosMain/c_interop/FirebaseDatabase.def index a8c61bc68..51e38d32b 100644 --- a/firebase-database/src/iosMain/c_interop/FirebaseDatabase.def +++ b/firebase-database/src/iosMain/c_interop/FirebaseDatabase.def @@ -1,4 +1,4 @@ language = Objective-C modules = FirebaseDatabase compilerOpts = -framework FirebaseDatabase -linkerOpts = -framework FirebaseDatabase +linkerOpts = -framework FirebaseDatabase -framework leveldb-library diff --git a/firebase-firestore/src/iosMain/c_interop/FirebaseFirestore.def b/firebase-firestore/src/iosMain/c_interop/FirebaseFirestore.def index 45927bef8..a66027b5b 100644 --- a/firebase-firestore/src/iosMain/c_interop/FirebaseFirestore.def +++ b/firebase-firestore/src/iosMain/c_interop/FirebaseFirestore.def @@ -1,4 +1,4 @@ language = Objective-C modules = FirebaseFirestore compilerOpts = -framework FirebaseFirestore -linkerOpts = -framework FirebaseFirestore +linkerOpts = -framework FirebaseFirestore -framework abseil -framework gRPC-Core -framework gRPC-C++ -framework BoringSSL-GRPC -framework leveldb-library diff --git a/firebase-functions/src/iosMain/c_interop/FirebaseFunctions.def b/firebase-functions/src/iosMain/c_interop/FirebaseFunctions.def index 27467487b..be86d1e56 100644 --- a/firebase-functions/src/iosMain/c_interop/FirebaseFunctions.def +++ b/firebase-functions/src/iosMain/c_interop/FirebaseFunctions.def @@ -1,4 +1,4 @@ language = Objective-C modules = FirebaseFunctions compilerOpts = -framework FirebaseFunctions -linkerOpts = -framework FirebaseFunctions +linkerOpts = -framework FirebaseFunctions -framework GTMSessionFetcher From 32814a1eefad2eaa9f667d459d2e83836ed21e9e Mon Sep 17 00:00:00 2001 From: Gijs van Veen Date: Wed, 19 Aug 2020 10:15:06 +0200 Subject: [PATCH 09/32] Add Test --- .../kotlin/dev/gitlive/firebase/auth/auth.kt | 12 ++++++++++++ 1 file changed, 12 insertions(+) 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 291dd7944..c01a21dda 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 @@ -50,6 +50,18 @@ class FirebaseAuthTest { signInResult.user!!.delete() } + @Test + fun testFetchSignInMethods() = runTest { + val email = "test+${Random.nextInt(100000)}@test.com" + var signInMethodResult = Firebase.auth.fetchSignInMethodsForEmail(email) + assertEquals(emptyList(), signInMethodResult.signInMethods) + Firebase.auth.createUserWithEmailAndPassword(email, "test123") + signInMethodResult = Firebase.auth.fetchSignInMethodsForEmail(email) + assertEquals(listOf("password"), signInMethodResult.signInMethods) + + Firebase.auth.signInWithEmailAndPassword(email, "test123").user!!.delete() + } + @Test fun testSendEmailVerification() = runTest { val email = "test+${Random.nextInt(100000)}@test.com" From d46ae845667a29205e2a2f98bd44e42dcfc73d8a Mon Sep 17 00:00:00 2001 From: Gijs van Veen Date: Wed, 19 Aug 2020 11:48:10 +0200 Subject: [PATCH 10/32] Fixed compile for tests --- firebase-app/build.gradle.kts | 24 +++++++++++--- .../src/iosMain/c_interop/FirebaseCore.def | 2 +- firebase-auth/build.gradle.kts | 17 ++++++---- firebase-database/build.gradle.kts | 24 ++++++++++++-- .../iosMain/c_interop/FirebaseDatabase.def | 2 +- firebase-firestore/build.gradle.kts | 31 +++++++++++++++++-- .../iosMain/c_interop/FirebaseFirestore.def | 2 +- firebase-functions/build.gradle.kts | 24 ++++++++++++-- .../iosMain/c_interop/FirebaseFunctions.def | 2 +- 9 files changed, 104 insertions(+), 24 deletions(-) diff --git a/firebase-app/build.gradle.kts b/firebase-app/build.gradle.kts index f97b2807b..7dcf08046 100644 --- a/firebase-app/build.gradle.kts +++ b/firebase-app/build.gradle.kts @@ -67,9 +67,16 @@ kotlin { val iosX64 = iosX64("ios") { binaries { getTest("DEBUG").apply { - linkerOpts("-F${rootProject.buildDir}/Firebase/FirebaseAnalytics/FirebaseCore.xcframework/ios-armv7_arm64", + linkerOpts( "-F${rootProject.buildDir}/Firebase/FirebaseAnalytics/FirebaseCore.xcframework/ios-i386_x86_64-simulator", - "-F${rootProject.buildDir}/Firebase/FirebaseAnalytics/FirebaseCore.xcframework/ios-x86_64-maccatalyst") + "-F${rootProject.buildDir}/Firebase/FirebaseAnalytics/FirebaseCoreDiagnostics.xcframework/ios-i386_x86_64-simulator", + "-F${rootProject.buildDir}/Firebase/FirebaseAnalytics/FirebaseInstallations.xcframework/ios-i386_x86_64-simulator", + "-F${rootProject.buildDir}/Firebase/FirebaseAnalytics/GoogleDataTransport.xcframework/ios-i386_x86_64-simulator", + "-F${rootProject.buildDir}/Firebase/FirebaseAnalytics/GoogleUtilities.xcframework/ios-i386_x86_64-simulator", + "-F${rootProject.buildDir}/Firebase/FirebaseAnalytics/nanopb.xcframework/ios-i386_x86_64-simulator", + "-F${rootProject.buildDir}/Firebase/FirebaseAnalytics/PromisesObjC.xcframework/ios-i386_x86_64-simulator", + "-F${rootProject.buildDir}/Firebase/FirebaseAnalytics" + ) linkerOpts("-ObjC") } } @@ -89,7 +96,7 @@ kotlin { } val androidMain by getting { dependencies { - api("com.google.firebase:firebase-common:19.2.0") + api("com.google.firebase:firebase-common:19.3.1") } } @@ -99,9 +106,16 @@ kotlin { val firebasecore by cinterops.creating { packageName("cocoapods.FirebaseCore") defFile(file("$projectDir/src/iosMain/c_interop/FirebaseCore.def")) - compilerOpts("-F${rootProject.buildDir}/Firebase/FirebaseAnalytics/FirebaseCore.xcframework/ios-armv7_arm64", + compilerOpts( "-F${rootProject.buildDir}/Firebase/FirebaseAnalytics/FirebaseCore.xcframework/ios-i386_x86_64-simulator", - "-F${rootProject.buildDir}/Firebase/FirebaseAnalytics/FirebaseCore.xcframework/ios-x86_64-maccatalyst") + "-F${rootProject.buildDir}/Firebase/FirebaseAnalytics/FirebaseCoreDiagnostics.xcframework/ios-i386_x86_64-simulator", + "-F${rootProject.buildDir}/Firebase/FirebaseAnalytics/FirebaseInstallations.xcframework/ios-i386_x86_64-simulator", + "-F${rootProject.buildDir}/Firebase/FirebaseAnalytics/GoogleDataTransport.xcframework/ios-i386_x86_64-simulator", + "-F${rootProject.buildDir}/Firebase/FirebaseAnalytics/GoogleUtilities.xcframework/ios-i386_x86_64-simulator", + "-F${rootProject.buildDir}/Firebase/FirebaseAnalytics/nanopb.xcframework/ios-i386_x86_64-simulator", + "-F${rootProject.buildDir}/Firebase/FirebaseAnalytics/PromisesObjC.xcframework/ios-i386_x86_64-simulator", + "-F${rootProject.buildDir}/Firebase/FirebaseAnalytics" + ) } } } diff --git a/firebase-app/src/iosMain/c_interop/FirebaseCore.def b/firebase-app/src/iosMain/c_interop/FirebaseCore.def index 8a7ad7e6a..d99f9484a 100644 --- a/firebase-app/src/iosMain/c_interop/FirebaseCore.def +++ b/firebase-app/src/iosMain/c_interop/FirebaseCore.def @@ -1,4 +1,4 @@ language = Objective-C modules = FirebaseCore compilerOpts = -framework FirebaseCore -linkerOpts = -framework FirebaseCore -framework abseil -framework gRPC-Core -framework gRPC-C++ -framework BoringSSL-GRPC -framework leveldb-library -framework GoogleUtilities -framework SystemConfiguration -framework FIRAnalyticsConnector -framework FirebaseAnalytics -framework FirebaseCore -framework FirebaseCoreDiagnostics -framework FirebaseInstallations -framework FirebaseInstanceID -framework GoogleAppMeasurement -framework GoogleDataTransport -framework GoogleUtilities -framework GTMSessionFetcher -framework PromisesObjC -framework nanopb -framework StoreKit -lsqlite3 +linkerOpts = -framework FirebaseCore -framework FirebaseCoreDiagnostics -framework FirebaseAnalytics -framework FIRAnalyticsConnector -framework GoogleAppMeasurement -framework FirebaseInstallations -framework GoogleDataTransport -framework GoogleUtilities -framework PromisesObjC -framework nanopb -framework StoreKit -lsqlite3 diff --git a/firebase-auth/build.gradle.kts b/firebase-auth/build.gradle.kts index c98dc3dcf..a2e9ebc3e 100644 --- a/firebase-auth/build.gradle.kts +++ b/firebase-auth/build.gradle.kts @@ -76,12 +76,17 @@ kotlin { val iosX64 = iosX64("ios") { binaries { getTest("DEBUG").apply { - linkerOpts("-F${rootProject.buildDir}/Firebase/FirebaseAnalytics/FirebaseCore.xcframework/ios-armv7_arm64", + linkerOpts( "-F${rootProject.buildDir}/Firebase/FirebaseAnalytics/FirebaseCore.xcframework/ios-i386_x86_64-simulator", - "-F${rootProject.buildDir}/Firebase/FirebaseAnalytics/FirebaseCore.xcframework/ios-x86_64-maccatalyst") - linkerOpts("-F${rootProject.buildDir}/Firebase/FirebaseAuth/FirebaseAuth.xcframework/ios-armv7_arm64", + "-F${rootProject.buildDir}/Firebase/FirebaseAnalytics/FirebaseCoreDiagnostics.xcframework/ios-i386_x86_64-simulator", + "-F${rootProject.buildDir}/Firebase/FirebaseAnalytics/FirebaseInstallations.xcframework/ios-i386_x86_64-simulator", + "-F${rootProject.buildDir}/Firebase/FirebaseAnalytics/GoogleDataTransport.xcframework/ios-i386_x86_64-simulator", + "-F${rootProject.buildDir}/Firebase/FirebaseAnalytics/GoogleUtilities.xcframework/ios-i386_x86_64-simulator", + "-F${rootProject.buildDir}/Firebase/FirebaseAnalytics/nanopb.xcframework/ios-i386_x86_64-simulator", + "-F${rootProject.buildDir}/Firebase/FirebaseAnalytics/PromisesObjC.xcframework/ios-i386_x86_64-simulator", + "-F${rootProject.buildDir}/Firebase/FirebaseAnalytics", "-F${rootProject.buildDir}/Firebase/FirebaseAuth/FirebaseAuth.xcframework/ios-i386_x86_64-simulator", - "-F${rootProject.buildDir}/Firebase/FirebaseAuth/FirebaseAuth.xcframework/ios-x86_64-maccatalyst") + "-F${rootProject.buildDir}/Firebase/FirebaseAuth/GTMSessionFetcher.xcframework/ios-i386_x86_64-simulator") linkerOpts("-F${rootProject.buildDir}/Firebase/GoogleSignIn") linkerOpts("-ObjC") // compilerOpts("-framework AppAuth") @@ -117,9 +122,9 @@ kotlin { val firebaseAuth by cinterops.creating { packageName("cocoapods.FirebaseAuth") defFile(file("$projectDir/src/iosMain/c_interop/FirebaseAuth.def")) - compilerOpts("-F${rootProject.buildDir}/Firebase/FirebaseAuth/FirebaseAuth.xcframework/ios-armv7_arm64", + compilerOpts( "-F${rootProject.buildDir}/Firebase/FirebaseAuth/FirebaseAuth.xcframework/ios-i386_x86_64-simulator", - "-F${rootProject.buildDir}/Firebase/FirebaseAuth/FirebaseAuth.xcframework/ios-x86_64-maccatalyst") + "-F${rootProject.buildDir}/Firebase/FirebaseAuth/GTMSessionFetcher.xcframework/ios-i386_x86_64-simulator") compilerOpts("-F$projectDir/../build/Firebase/GoogleSignIn") } } diff --git a/firebase-database/build.gradle.kts b/firebase-database/build.gradle.kts index f3419f0b6..1c3c4bfa1 100644 --- a/firebase-database/build.gradle.kts +++ b/firebase-database/build.gradle.kts @@ -52,7 +52,25 @@ kotlin { publishLibraryVariants("release", "debug") } val iosArm64 = iosArm64() - val iosX64 = iosX64("ios") + val iosX64 = iosX64("ios") { + binaries { + getTest("DEBUG").apply { + linkerOpts( + "-F${rootProject.buildDir}/Firebase/FirebaseAnalytics/FirebaseCore.xcframework/ios-i386_x86_64-simulator", + "-F${rootProject.buildDir}/Firebase/FirebaseAnalytics/FirebaseCoreDiagnostics.xcframework/ios-i386_x86_64-simulator", + "-F${rootProject.buildDir}/Firebase/FirebaseAnalytics/FirebaseInstallations.xcframework/ios-i386_x86_64-simulator", + "-F${rootProject.buildDir}/Firebase/FirebaseAnalytics/GoogleDataTransport.xcframework/ios-i386_x86_64-simulator", + "-F${rootProject.buildDir}/Firebase/FirebaseAnalytics/GoogleUtilities.xcframework/ios-i386_x86_64-simulator", + "-F${rootProject.buildDir}/Firebase/FirebaseAnalytics/nanopb.xcframework/ios-i386_x86_64-simulator", + "-F${rootProject.buildDir}/Firebase/FirebaseAnalytics/PromisesObjC.xcframework/ios-i386_x86_64-simulator", + "-F${rootProject.buildDir}/Firebase/FirebaseAnalytics", + "-F${rootProject.buildDir}/Firebase/FirebaseDatabase/FirebaseDatabase.xcframework/ios-i386_x86_64-simulator", + "-F${rootProject.buildDir}/Firebase/FirebaseDatabase/leveldb-library.xcframework/ios-i386_x86_64-simulator" + ) + linkerOpts("-ObjC") + } + } + } tasks.withType> { kotlinOptions.freeCompilerArgs += listOf( @@ -83,9 +101,9 @@ kotlin { val firebaseDatabase by cinterops.creating { packageName("cocoapods.FirebaseDatabase") defFile(file("$projectDir/src/iosMain/c_interop/FirebaseDatabase.def")) - compilerOpts("-F${rootProject.buildDir}/Firebase/FirebaseDatabase/FirebaseDatabase.xcframework/ios-armv7_arm64", + compilerOpts( "-F${rootProject.buildDir}/Firebase/FirebaseDatabase/FirebaseDatabase.xcframework/ios-i386_x86_64-simulator", - "-F${rootProject.buildDir}/Firebase/FirebaseDatabase/FirebaseDatabase.xcframework/ios-x86_64-maccatalyst") + "-F${rootProject.buildDir}/Firebase/FirebaseDatabase/leveldb-library.xcframework/ios-i386_x86_64-simulator") } } } diff --git a/firebase-database/src/iosMain/c_interop/FirebaseDatabase.def b/firebase-database/src/iosMain/c_interop/FirebaseDatabase.def index a8c61bc68..51e38d32b 100644 --- a/firebase-database/src/iosMain/c_interop/FirebaseDatabase.def +++ b/firebase-database/src/iosMain/c_interop/FirebaseDatabase.def @@ -1,4 +1,4 @@ language = Objective-C modules = FirebaseDatabase compilerOpts = -framework FirebaseDatabase -linkerOpts = -framework FirebaseDatabase +linkerOpts = -framework FirebaseDatabase -framework leveldb-library diff --git a/firebase-firestore/build.gradle.kts b/firebase-firestore/build.gradle.kts index 3297be269..072357d9d 100644 --- a/firebase-firestore/build.gradle.kts +++ b/firebase-firestore/build.gradle.kts @@ -48,7 +48,29 @@ kotlin { publishLibraryVariants("release", "debug") } val iosArm64 = iosArm64() - val iosX64 = iosX64("ios") + val iosX64 = iosX64("ios") { + binaries { + getTest("DEBUG").apply { + linkerOpts( + "-F${rootProject.buildDir}/Firebase/FirebaseAnalytics/FirebaseCore.xcframework/ios-i386_x86_64-simulator", + "-F${rootProject.buildDir}/Firebase/FirebaseAnalytics/FirebaseCoreDiagnostics.xcframework/ios-i386_x86_64-simulator", + "-F${rootProject.buildDir}/Firebase/FirebaseAnalytics/FirebaseInstallations.xcframework/ios-i386_x86_64-simulator", + "-F${rootProject.buildDir}/Firebase/FirebaseAnalytics/GoogleDataTransport.xcframework/ios-i386_x86_64-simulator", + "-F${rootProject.buildDir}/Firebase/FirebaseAnalytics/GoogleUtilities.xcframework/ios-i386_x86_64-simulator", + "-F${rootProject.buildDir}/Firebase/FirebaseAnalytics/nanopb.xcframework/ios-i386_x86_64-simulator", + "-F${rootProject.buildDir}/Firebase/FirebaseAnalytics/PromisesObjC.xcframework/ios-i386_x86_64-simulator", + "-F${rootProject.buildDir}/Firebase/FirebaseAnalytics", + "-F${rootProject.buildDir}/Firebase/FirebaseFirestore/FirebaseFirestore.xcframework/ios-i386_x86_64-simulator", + "-F${rootProject.buildDir}/Firebase/FirebaseFirestore/abseil.xcframework/ios-i386_x86_64-simulator", + "-F${rootProject.buildDir}/Firebase/FirebaseFirestore/BoringSSL-GRPC.xcframework/ios-i386_x86_64-simulator", + "-F${rootProject.buildDir}/Firebase/FirebaseFirestore/gRPC-C++.xcframework/ios-i386_x86_64-simulator", + "-F${rootProject.buildDir}/Firebase/FirebaseFirestore/gRPC-Core.xcframework/ios-i386_x86_64-simulator", + "-F${rootProject.buildDir}/Firebase/FirebaseFirestore/leveldb-library.xcframework/ios-i386_x86_64-simulator" + ) + linkerOpts("-ObjC") + } + } + } tasks.withType> { kotlinOptions.freeCompilerArgs += listOf( @@ -82,9 +104,12 @@ kotlin { packageName("cocoapods.FirebaseFirestore") defFile(file("$projectDir/src/iosMain/c_interop/FirebaseFirestore.def")) compilerOpts( - "-F${rootProject.buildDir}/Firebase/FirebaseFirestore/FirebaseFirestore.xcframework/ios-armv7_arm64", "-F${rootProject.buildDir}/Firebase/FirebaseFirestore/FirebaseFirestore.xcframework/ios-i386_x86_64-simulator", - "-F${rootProject.buildDir}/Firebase/FirebaseFirestore/FirebaseFirestore.xcframework/ios-x86_64-maccatalyst" + "-F${rootProject.buildDir}/Firebase/FirebaseFirestore/abseil.xcframework/ios-i386_x86_64-simulator", + "-F${rootProject.buildDir}/Firebase/FirebaseFirestore/BoringSSL-GRPC.xcframework/ios-i386_x86_64-simulator", + "-F${rootProject.buildDir}/Firebase/FirebaseFirestore/gRPC-C++.xcframework/ios-i386_x86_64-simulator", + "-F${rootProject.buildDir}/Firebase/FirebaseFirestore/gRPC-Core.xcframework/ios-i386_x86_64-simulator", + "-F${rootProject.buildDir}/Firebase/FirebaseFirestore/leveldb-library.xcframework/ios-i386_x86_64-simulator" ) } } diff --git a/firebase-firestore/src/iosMain/c_interop/FirebaseFirestore.def b/firebase-firestore/src/iosMain/c_interop/FirebaseFirestore.def index 45927bef8..a66027b5b 100644 --- a/firebase-firestore/src/iosMain/c_interop/FirebaseFirestore.def +++ b/firebase-firestore/src/iosMain/c_interop/FirebaseFirestore.def @@ -1,4 +1,4 @@ language = Objective-C modules = FirebaseFirestore compilerOpts = -framework FirebaseFirestore -linkerOpts = -framework FirebaseFirestore +linkerOpts = -framework FirebaseFirestore -framework abseil -framework gRPC-Core -framework gRPC-C++ -framework BoringSSL-GRPC -framework leveldb-library diff --git a/firebase-functions/build.gradle.kts b/firebase-functions/build.gradle.kts index a4385da0e..d79e1b9fa 100644 --- a/firebase-functions/build.gradle.kts +++ b/firebase-functions/build.gradle.kts @@ -46,7 +46,25 @@ kotlin { publishLibraryVariants("release", "debug") } val iosArm64 = iosArm64() - val iosX64 = iosX64("ios") + val iosX64 = iosX64("ios") { + binaries { + getTest("DEBUG").apply { + linkerOpts( + "-F${rootProject.buildDir}/Firebase/FirebaseAnalytics/FirebaseCore.xcframework/ios-i386_x86_64-simulator", + "-F${rootProject.buildDir}/Firebase/FirebaseAnalytics/FirebaseCoreDiagnostics.xcframework/ios-i386_x86_64-simulator", + "-F${rootProject.buildDir}/Firebase/FirebaseAnalytics/FirebaseInstallations.xcframework/ios-i386_x86_64-simulator", + "-F${rootProject.buildDir}/Firebase/FirebaseAnalytics/GoogleDataTransport.xcframework/ios-i386_x86_64-simulator", + "-F${rootProject.buildDir}/Firebase/FirebaseAnalytics/GoogleUtilities.xcframework/ios-i386_x86_64-simulator", + "-F${rootProject.buildDir}/Firebase/FirebaseAnalytics/nanopb.xcframework/ios-i386_x86_64-simulator", + "-F${rootProject.buildDir}/Firebase/FirebaseAnalytics/PromisesObjC.xcframework/ios-i386_x86_64-simulator", + "-F${rootProject.buildDir}/Firebase/FirebaseAnalytics", + "-F${rootProject.buildDir}/Firebase/FirebaseFunctions/FirebaseFunctions.xcframework/ios-i386_x86_64-simulator", + "-F${rootProject.buildDir}/Firebase/FirebaseFunctions/GTMSessionFetcher.xcframework/ios-i386_x86_64-simulator" + ) + linkerOpts("-ObjC") + } + } + } tasks.withType> { kotlinOptions.freeCompilerArgs += listOf( @@ -77,9 +95,9 @@ kotlin { val firebasefunctions by cinterops.creating { packageName("cocoapods.FirebaseFunctions") defFile(file("$projectDir/src/iosMain/c_interop/FirebaseFunctions.def")) - compilerOpts("-F${rootProject.buildDir}/Firebase/FirebaseFunctions/FirebaseFunctions.xcframework/ios-armv7_arm64", + compilerOpts( "-F${rootProject.buildDir}/Firebase/FirebaseFunctions/FirebaseFunctions.xcframework/ios-i386_x86_64-simulator", - "-F${rootProject.buildDir}/Firebase/FirebaseFunctions/FirebaseFunctions.xcframework/ios-x86_64-maccatalyst") + "-F${rootProject.buildDir}/Firebase/FirebaseFunctions/GTMSessionFetcher.xcframework/ios-i386_x86_64-simulator") } } } diff --git a/firebase-functions/src/iosMain/c_interop/FirebaseFunctions.def b/firebase-functions/src/iosMain/c_interop/FirebaseFunctions.def index 27467487b..be86d1e56 100644 --- a/firebase-functions/src/iosMain/c_interop/FirebaseFunctions.def +++ b/firebase-functions/src/iosMain/c_interop/FirebaseFunctions.def @@ -1,4 +1,4 @@ language = Objective-C modules = FirebaseFunctions compilerOpts = -framework FirebaseFunctions -linkerOpts = -framework FirebaseFunctions +linkerOpts = -framework FirebaseFunctions -framework GTMSessionFetcher From 58c866dca70b1502a73515fb339abb80e864adf1 Mon Sep 17 00:00:00 2001 From: Gijs van Veen Date: Wed, 19 Aug 2020 16:19:22 +0200 Subject: [PATCH 11/32] Add missing firetore frameworks --- firebase-firestore/src/iosMain/c_interop/FirebaseFirestore.def | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/firebase-firestore/src/iosMain/c_interop/FirebaseFirestore.def b/firebase-firestore/src/iosMain/c_interop/FirebaseFirestore.def index a66027b5b..3bfe7405c 100644 --- a/firebase-firestore/src/iosMain/c_interop/FirebaseFirestore.def +++ b/firebase-firestore/src/iosMain/c_interop/FirebaseFirestore.def @@ -1,4 +1,4 @@ language = Objective-C modules = FirebaseFirestore compilerOpts = -framework FirebaseFirestore -linkerOpts = -framework FirebaseFirestore -framework abseil -framework gRPC-Core -framework gRPC-C++ -framework BoringSSL-GRPC -framework leveldb-library +linkerOpts = -framework FirebaseFirestore -framework abseil -framework gRPC-Core -framework gRPC-C++ -framework BoringSSL-GRPC -framework leveldb-library -framework SystemConfiguration -framework MobileCoreServices From 6dc7a470abc3cbdaf684c88f784c7a6b7586f8dc Mon Sep 17 00:00:00 2001 From: Gijs van Veen Date: Thu, 20 Aug 2020 17:49:13 +0200 Subject: [PATCH 12/32] Account for nullable results --- .../kotlin/dev/gitlive/firebase/auth/auth.kt | 52 +++++++++++++++---- .../dev/gitlive/firebase/auth/credentials.kt | 4 +- .../dev/gitlive/firebase/auth/multifactor.kt | 4 +- .../kotlin/dev/gitlive/firebase/auth/user.kt | 6 +-- 4 files changed, 49 insertions(+), 17 deletions(-) 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 8822f7854..e753a37be 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 @@ -41,15 +41,15 @@ actual class FirebaseAuth internal constructor(val ios: FIRAuth) { set(value) { ios.setLanguageCode(value) } actual suspend fun applyActionCode(code: String) = ios.await { applyActionCode(code, it) }.run { Unit } - actual suspend fun checkActionCode(code: String): ActionCodeResult = ActionCodeResult(ios.awaitResult { checkActionCode(code, it) }) + actual suspend fun checkActionCode(code: String): ActionCodeResult = ActionCodeResult(ios.awaitExpectedResult { checkActionCode(code, it) }) actual suspend fun confirmPasswordReset(code: String, newPassword: String) = ios.await { confirmPasswordResetWithCode(code, newPassword, it) }.run { Unit } actual suspend fun createUserWithEmailAndPassword(email: String, password: String) = - AuthResult(ios.awaitResult { createUserWithEmail(email = email, password = password, completion = it) }) + AuthResult(ios.awaitExpectedResult { createUserWithEmail(email = email, password = password, completion = it) }) actual suspend fun fetchSignInMethodsForEmail(email: String): SignInMethodQueryResult { - val signInMethods: List<*> = ios.awaitResult { fetchSignInMethodsForEmail(email, it) } - return SignInMethodQueryResult(signInMethods.mapNotNull { it as String }) + val signInMethods: List<*>? = ios.awaitResult { fetchSignInMethodsForEmail(email, it) } + return SignInMethodQueryResult(signInMethods?.mapNotNull { it as String } ?: emptyList()) } actual suspend fun sendPasswordResetEmail(email: String, actionCodeSettings: ActionCodeSettings?) { @@ -59,21 +59,21 @@ actual class FirebaseAuth internal constructor(val ios: FIRAuth) { actual suspend fun sendSignInLinkToEmail(email: String, actionCodeSettings: ActionCodeSettings) = ios.await { sendSignInLinkToEmail(email, actionCodeSettings.ios, it) }.run { Unit } actual suspend fun signInWithEmailAndPassword(email: String, password: String) = - AuthResult(ios.awaitResult { signInWithEmail(email = email, password = password, completion = it) }) + AuthResult(ios.awaitExpectedResult { signInWithEmail(email = email, password = password, completion = it) }) actual suspend fun signInWithCustomToken(token: String) = - AuthResult(ios.awaitResult { signInWithCustomToken(token, it) }) + AuthResult(ios.awaitExpectedResult { signInWithCustomToken(token, it) }) actual suspend fun signInAnonymously() = - AuthResult(ios.awaitResult { signInAnonymouslyWithCompletion(it) }) + AuthResult(ios.awaitExpectedResult { signInAnonymouslyWithCompletion(it) }) actual suspend fun signInWithCredential(authCredential: AuthCredential) = - AuthResult(ios.awaitResult { signInWithCredential(authCredential.ios, it) }) + AuthResult(ios.awaitExpectedResult { signInWithCredential(authCredential.ios, it) }) actual suspend fun signOut() = ios.throwError { signOut(it) }.run { Unit } actual suspend fun updateCurrentUser(user: FirebaseUser) = ios.await { updateCurrentUser(user.ios, it) }.run { Unit } - actual suspend fun verifyPasswordResetCode(code: String): String = ios.awaitResult { verifyPasswordResetCode(code, it) } + actual suspend fun verifyPasswordResetCode(code: String): String = ios.awaitExpectedResult { verifyPasswordResetCode(code, it) } } actual class AuthResult internal constructor(val ios: FIRAuthDataResult) { @@ -147,6 +147,10 @@ actual open class FirebaseAuthRecentLoginRequiredException(message: String): Fir actual open class FirebaseAuthUserCollisionException(message: String): FirebaseAuthException(message) actual open class FirebaseAuthWebException(message: String): FirebaseAuthException(message) +class UnexpectedNullResultException : Exception() { + override val message: String? = "The API encountered an unexpected null result" +} + internal fun T.throwError(block: T.(errorPointer: CPointer>) -> R): R { memScoped { val errorPointer: CPointer> = alloc>().ptr @@ -159,13 +163,41 @@ internal fun T.throwError(block: T.(errorPointer: CPointer T.awaitResult(function: T.(callback: (R?, NSError?) -> Unit) -> Unit): R { +internal suspend fun T.awaitResult(function: T.(callback: (R?, NSError?) -> Unit) -> Unit): R? { + val job = CompletableDeferred() + function { result, error -> + if(error != null) { + job.completeExceptionally(error.toException()) + } else { + job.complete(result) + } + } + return job.await() +} + +internal suspend fun T.awaitResult(default: R, function: T.(callback: (R?, NSError?) -> Unit) -> Unit): R { + val job = CompletableDeferred() + function { result, error -> + if(result != null) { + job.complete(result) + } else if(error != null) { + job.completeExceptionally(error.toException()) + } else { + job.complete(default) + } + } + return job.await() +} + +internal suspend fun T.awaitExpectedResult(function: T.(callback: (R?, NSError?) -> Unit) -> Unit): R { val job = CompletableDeferred() function { result, error -> if(result != null) { job.complete(result) } else if(error != null) { job.completeExceptionally(error.toException()) + } else { + job.completeExceptionally(UnexpectedNullResultException()) } } return job.await() diff --git a/firebase-auth/src/iosMain/kotlin/dev/gitlive/firebase/auth/credentials.kt b/firebase-auth/src/iosMain/kotlin/dev/gitlive/firebase/auth/credentials.kt index 6192c47b0..8be084064 100644 --- a/firebase-auth/src/iosMain/kotlin/dev/gitlive/firebase/auth/credentials.kt +++ b/firebase-auth/src/iosMain/kotlin/dev/gitlive/firebase/auth/credentials.kt @@ -63,7 +63,7 @@ actual class OAuthProvider(val ios: FIROAuthProvider, private val auth: Firebase null}.toMap() } - actual suspend fun signIn(signInProvider: SignInProvider): AuthResult = AuthResult(ios.awaitResult { auth.ios.signInWithProvider(ios, signInProvider.delegate, it) }) + actual suspend fun signIn(signInProvider: SignInProvider): AuthResult = AuthResult(ios.awaitExpectedResult { auth.ios.signInWithProvider(ios, signInProvider.delegate, it) }) } actual class SignInProvider(val delegate: FIRAuthUIDelegateProtocol) @@ -74,7 +74,7 @@ actual class PhoneAuthProvider(val ios: FIRPhoneAuthProvider) { actual fun credentialWithVerificationIdAndSmsCode(verificationId: String, smsCode: String): PhoneAuthCredential = PhoneAuthCredential(ios.credentialWithVerificationID(verificationId, smsCode)) actual suspend fun verifyPhoneNumber(phoneNumber: String, verificationProvider: PhoneVerificationProvider): AuthCredential { - val verificationId: String = ios.awaitResult { ios.verifyPhoneNumber(phoneNumber, verificationProvider.delegate, it) } + val verificationId: String = ios.awaitExpectedResult { ios.verifyPhoneNumber(phoneNumber, verificationProvider.delegate, it) } val verificationCode = verificationProvider.getVerificationCode() return credentialWithVerificationIdAndSmsCode(verificationId, verificationCode) } diff --git a/firebase-auth/src/iosMain/kotlin/dev/gitlive/firebase/auth/multifactor.kt b/firebase-auth/src/iosMain/kotlin/dev/gitlive/firebase/auth/multifactor.kt index 757732511..55942b98e 100644 --- a/firebase-auth/src/iosMain/kotlin/dev/gitlive/firebase/auth/multifactor.kt +++ b/firebase-auth/src/iosMain/kotlin/dev/gitlive/firebase/auth/multifactor.kt @@ -10,7 +10,7 @@ actual class MultiFactor(val ios: FIRMultiFactor) { actual val enrolledFactors: List get() = ios.enrolledFactors.mapNotNull { info -> (info as? FIRMultiFactorInfo)?.let{ MultiFactorInfo(it) } } actual suspend fun enroll(multiFactorAssertion: MultiFactorAssertion, displayName: String?) = ios.await { enrollWithAssertion(multiFactorAssertion.ios, displayName, it) }.run { Unit } - actual suspend fun getSession(): MultiFactorSession = MultiFactorSession(ios.awaitResult { getSessionWithCompletion(completion = it) }) + actual suspend fun getSession(): MultiFactorSession = MultiFactorSession(ios.awaitExpectedResult { getSessionWithCompletion(completion = it) }) actual suspend fun unenroll(multiFactorInfo: MultiFactorInfo) = ios.await { unenrollWithInfo(multiFactorInfo.ios, it) }.run { Unit } actual suspend fun unenroll(factorUid: String) = ios.await { unenrollWithFactorUID(factorUid, it) }.run { Unit } } @@ -38,5 +38,5 @@ actual class MultiFactorResolver(val ios: FIRMultiFactorResolver) { actual val hints: List = ios.hints.mapNotNull { hint -> (hint as? FIRMultiFactorInfo)?.let { MultiFactorInfo(it) } } actual val session: MultiFactorSession = MultiFactorSession(ios.session) - actual suspend fun resolveSignIn(assertion: MultiFactorAssertion): AuthResult = AuthResult(ios.awaitResult { resolveSignInWithAssertion(assertion.ios, it) }) + actual suspend fun resolveSignIn(assertion: MultiFactorAssertion): AuthResult = AuthResult(ios.awaitExpectedResult { resolveSignInWithAssertion(assertion.ios, it) }) } \ No newline at end of file diff --git a/firebase-auth/src/iosMain/kotlin/dev/gitlive/firebase/auth/user.kt b/firebase-auth/src/iosMain/kotlin/dev/gitlive/firebase/auth/user.kt index af83cca4c..52345d783 100644 --- a/firebase-auth/src/iosMain/kotlin/dev/gitlive/firebase/auth/user.kt +++ b/firebase-auth/src/iosMain/kotlin/dev/gitlive/firebase/auth/user.kt @@ -33,11 +33,11 @@ actual class FirebaseUser internal constructor(val ios: FIRUser) { actual suspend fun delete() = ios.await { deleteWithCompletion(it) }.run { Unit } actual suspend fun reload() = ios.await { reloadWithCompletion(it) }.run { Unit } actual suspend fun getIdToken(forceRefresh: Boolean): String? = ios.awaitResult { getIDTokenForcingRefresh(forceRefresh, it) } - actual suspend fun linkWithCredential(credential: AuthCredential): AuthResult = AuthResult(ios.awaitResult { linkWithCredential(credential.ios, it) }) + actual suspend fun linkWithCredential(credential: AuthCredential): AuthResult = AuthResult(ios.awaitExpectedResult { linkWithCredential(credential.ios, it) }) actual suspend fun reauthenticate(credential: AuthCredential) { - val result: FIRAuthDataResult = ios.awaitResult { reauthenticateWithCredential(credential.ios, it) } + val result: FIRAuthDataResult = ios.awaitExpectedResult { reauthenticateWithCredential(credential.ios, it) } } - actual suspend fun reauthenticateAndRetrieveData(credential: AuthCredential): AuthResult = AuthResult(ios.awaitResult { reauthenticateWithCredential(credential.ios, it) }) + actual suspend fun reauthenticateAndRetrieveData(credential: AuthCredential): AuthResult = AuthResult(ios.awaitExpectedResult { reauthenticateWithCredential(credential.ios, it) }) actual suspend fun sendEmailVerification(actionCodeSettings: ActionCodeSettings?) = ios.await { actionCodeSettings?.let { actionSettings -> sendEmailVerificationWithActionCodeSettings(actionSettings.ios, it) } ?: sendEmailVerificationWithCompletion(it) From 138dd4cd6dc84d61195944443726983a6e40f78b Mon Sep 17 00:00:00 2001 From: Gijs van Veen Date: Fri, 21 Aug 2020 15:56:29 +0200 Subject: [PATCH 13/32] Use Carthage instead of zip for linking. This cleans up dependencies and reduces build time --- .gitignore | 4 ++ build.gradle.kts | 57 +++++++++---------- firebase-app/build.gradle.kts | 22 +------ firebase-app/src/iosMain/c_interop/Cartfile | 1 + firebase-auth/build.gradle.kts | 19 ++----- firebase-auth/src/iosMain/c_interop/Cartfile | 1 + firebase-database/build.gradle.kts | 16 +----- .../src/iosMain/c_interop/Cartfile | 1 + firebase-firestore/build.gradle.kts | 25 +------- .../src/iosMain/c_interop/Cartfile | 1 + firebase-functions/build.gradle.kts | 16 +----- .../src/iosMain/c_interop/Cartfile | 1 + 12 files changed, 51 insertions(+), 113 deletions(-) create mode 100644 firebase-app/src/iosMain/c_interop/Cartfile create mode 100644 firebase-auth/src/iosMain/c_interop/Cartfile create mode 100644 firebase-database/src/iosMain/c_interop/Cartfile create mode 100644 firebase-firestore/src/iosMain/c_interop/Cartfile create mode 100644 firebase-functions/src/iosMain/c_interop/Cartfile diff --git a/.gitignore b/.gitignore index 3d87e8e84..ccc803fac 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,7 @@ firebase-database/src/iosMain/c_interop/modules/ Firebase*.zip /Firebase /.DS_Store + + +/**/Cartfile.resolved +/**/c_interop/Carthage/ diff --git a/build.gradle.kts b/build.gradle.kts index 7fa5cad10..b66eb9599 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -28,31 +28,6 @@ buildscript { val targetSdkVersion by extra(28) val minSdkVersion by extra(16) - -tasks { - val downloadIOSFirebaseZipFile by creating(Download::class) { - src("https://github.com/firebase/firebase-ios-sdk/releases/download/CocoaPods-6.30.0/Firebase.zip") - dest(File(buildDir, "Firebase-6.30.0.zip")) - if (System.getenv("token") != null) { - username(System.getenv("token")) - } - overwrite(false) - } - - val unzipIOSFirebase by creating(Copy::class) { - if (!File("$buildDir/Firebase").exists()) { - val zipFile = File(buildDir, "Firebase-6.30.0.zip") - if (!zipFile.exists()) { - dependsOn(downloadIOSFirebaseZipFile) - } - from(zipTree(zipFile)) - into(buildDir) - } - outputs.upToDateWhen { File("$buildDir/Firebase").isDirectory } - } - -} - subprojects { group = "dev.gitlive" @@ -147,6 +122,29 @@ subprojects { ) } } + + listOf("bootstrap", "update").forEach { + task("carthage${it.capitalize()}") { + group = "carthage" + executable = "carthage" + args( + it, + "--project-directory", "src/iosMain/c_interop", + "--platform", "iOS", + "--cache-builds" + ) + } + } + + withType(org.jetbrains.kotlin.gradle.tasks.CInteropProcess::class) { + dependsOn("carthageBootstrap") + } + + create("carthageClean", Delete::class.java) { + group = "carthage" + delete(File("$projectDir/src/iosMain/c_interop/Carthage")) + delete(File("$projectDir/src/iosMain/c_interop/Cartfile.resolved")) + } } // tasks.withType> { @@ -163,13 +161,10 @@ subprojects { mkdir("$buildDir/node_module") } - if(Os.isFamily(Os.FAMILY_MAC)) { - tasks.getByPath("compileKotlinIos").dependsOn(rootProject.tasks.named("unzipIOSFirebase")) - } else { - println("Skipping Firebase zip download") + tasks.named("clean") { + dependsOn("carthageClean") } - dependencies { "commonMainImplementation"(kotlin("stdlib-common")) "commonMainImplementation"("org.jetbrains.kotlinx:kotlinx-coroutines-core-common:1.3.8") @@ -191,6 +186,8 @@ subprojects { "androidAndroidTestImplementation"("androidx.test.ext:junit:1.1.1") "androidAndroidTestImplementation"("androidx.test:runner:1.2.0") } + + } apply(plugin="maven-publish") diff --git a/firebase-app/build.gradle.kts b/firebase-app/build.gradle.kts index 7dcf08046..716f6f4c5 100644 --- a/firebase-app/build.gradle.kts +++ b/firebase-app/build.gradle.kts @@ -67,16 +67,7 @@ kotlin { val iosX64 = iosX64("ios") { binaries { getTest("DEBUG").apply { - linkerOpts( - "-F${rootProject.buildDir}/Firebase/FirebaseAnalytics/FirebaseCore.xcframework/ios-i386_x86_64-simulator", - "-F${rootProject.buildDir}/Firebase/FirebaseAnalytics/FirebaseCoreDiagnostics.xcframework/ios-i386_x86_64-simulator", - "-F${rootProject.buildDir}/Firebase/FirebaseAnalytics/FirebaseInstallations.xcframework/ios-i386_x86_64-simulator", - "-F${rootProject.buildDir}/Firebase/FirebaseAnalytics/GoogleDataTransport.xcframework/ios-i386_x86_64-simulator", - "-F${rootProject.buildDir}/Firebase/FirebaseAnalytics/GoogleUtilities.xcframework/ios-i386_x86_64-simulator", - "-F${rootProject.buildDir}/Firebase/FirebaseAnalytics/nanopb.xcframework/ios-i386_x86_64-simulator", - "-F${rootProject.buildDir}/Firebase/FirebaseAnalytics/PromisesObjC.xcframework/ios-i386_x86_64-simulator", - "-F${rootProject.buildDir}/Firebase/FirebaseAnalytics" - ) + linkerOpts("-F$projectDir/src/iosMain/c_interop/Carthage/Build/iOS/") linkerOpts("-ObjC") } } @@ -106,16 +97,7 @@ kotlin { val firebasecore by cinterops.creating { packageName("cocoapods.FirebaseCore") defFile(file("$projectDir/src/iosMain/c_interop/FirebaseCore.def")) - compilerOpts( - "-F${rootProject.buildDir}/Firebase/FirebaseAnalytics/FirebaseCore.xcframework/ios-i386_x86_64-simulator", - "-F${rootProject.buildDir}/Firebase/FirebaseAnalytics/FirebaseCoreDiagnostics.xcframework/ios-i386_x86_64-simulator", - "-F${rootProject.buildDir}/Firebase/FirebaseAnalytics/FirebaseInstallations.xcframework/ios-i386_x86_64-simulator", - "-F${rootProject.buildDir}/Firebase/FirebaseAnalytics/GoogleDataTransport.xcframework/ios-i386_x86_64-simulator", - "-F${rootProject.buildDir}/Firebase/FirebaseAnalytics/GoogleUtilities.xcframework/ios-i386_x86_64-simulator", - "-F${rootProject.buildDir}/Firebase/FirebaseAnalytics/nanopb.xcframework/ios-i386_x86_64-simulator", - "-F${rootProject.buildDir}/Firebase/FirebaseAnalytics/PromisesObjC.xcframework/ios-i386_x86_64-simulator", - "-F${rootProject.buildDir}/Firebase/FirebaseAnalytics" - ) + compilerOpts("-F$projectDir/src/iosMain/c_interop/Carthage/Build/iOS/") } } } diff --git a/firebase-app/src/iosMain/c_interop/Cartfile b/firebase-app/src/iosMain/c_interop/Cartfile new file mode 100644 index 000000000..1bd6d95cc --- /dev/null +++ b/firebase-app/src/iosMain/c_interop/Cartfile @@ -0,0 +1 @@ +binary "https://dl.google.com/dl/firebase/ios/carthage/FirebaseAnalyticsBinary.json" == 6.30.0 \ No newline at end of file diff --git a/firebase-auth/build.gradle.kts b/firebase-auth/build.gradle.kts index a2e9ebc3e..52f00e6ce 100644 --- a/firebase-auth/build.gradle.kts +++ b/firebase-auth/build.gradle.kts @@ -77,19 +77,9 @@ kotlin { binaries { getTest("DEBUG").apply { linkerOpts( - "-F${rootProject.buildDir}/Firebase/FirebaseAnalytics/FirebaseCore.xcframework/ios-i386_x86_64-simulator", - "-F${rootProject.buildDir}/Firebase/FirebaseAnalytics/FirebaseCoreDiagnostics.xcframework/ios-i386_x86_64-simulator", - "-F${rootProject.buildDir}/Firebase/FirebaseAnalytics/FirebaseInstallations.xcframework/ios-i386_x86_64-simulator", - "-F${rootProject.buildDir}/Firebase/FirebaseAnalytics/GoogleDataTransport.xcframework/ios-i386_x86_64-simulator", - "-F${rootProject.buildDir}/Firebase/FirebaseAnalytics/GoogleUtilities.xcframework/ios-i386_x86_64-simulator", - "-F${rootProject.buildDir}/Firebase/FirebaseAnalytics/nanopb.xcframework/ios-i386_x86_64-simulator", - "-F${rootProject.buildDir}/Firebase/FirebaseAnalytics/PromisesObjC.xcframework/ios-i386_x86_64-simulator", - "-F${rootProject.buildDir}/Firebase/FirebaseAnalytics", - "-F${rootProject.buildDir}/Firebase/FirebaseAuth/FirebaseAuth.xcframework/ios-i386_x86_64-simulator", - "-F${rootProject.buildDir}/Firebase/FirebaseAuth/GTMSessionFetcher.xcframework/ios-i386_x86_64-simulator") - linkerOpts("-F${rootProject.buildDir}/Firebase/GoogleSignIn") + "-F${rootProject.projectDir}/firebase-app/src/iosMain/c_interop/Carthage/Build/iOS/", + "-F$projectDir/src/iosMain/c_interop/Carthage/Build/iOS/") linkerOpts("-ObjC") -// compilerOpts("-framework AppAuth") } } } @@ -123,9 +113,8 @@ kotlin { packageName("cocoapods.FirebaseAuth") defFile(file("$projectDir/src/iosMain/c_interop/FirebaseAuth.def")) compilerOpts( - "-F${rootProject.buildDir}/Firebase/FirebaseAuth/FirebaseAuth.xcframework/ios-i386_x86_64-simulator", - "-F${rootProject.buildDir}/Firebase/FirebaseAuth/GTMSessionFetcher.xcframework/ios-i386_x86_64-simulator") - compilerOpts("-F$projectDir/../build/Firebase/GoogleSignIn") + "-F$projectDir/src/iosMain/c_interop/Carthage/Build/iOS/" + ) } } } diff --git a/firebase-auth/src/iosMain/c_interop/Cartfile b/firebase-auth/src/iosMain/c_interop/Cartfile new file mode 100644 index 000000000..bd6a565fb --- /dev/null +++ b/firebase-auth/src/iosMain/c_interop/Cartfile @@ -0,0 +1 @@ +binary "https://dl.google.com/dl/firebase/ios/carthage/FirebaseAuthBinary.json" == 6.30.0 \ No newline at end of file diff --git a/firebase-database/build.gradle.kts b/firebase-database/build.gradle.kts index 1c3c4bfa1..36dce0f7c 100644 --- a/firebase-database/build.gradle.kts +++ b/firebase-database/build.gradle.kts @@ -56,16 +56,8 @@ kotlin { binaries { getTest("DEBUG").apply { linkerOpts( - "-F${rootProject.buildDir}/Firebase/FirebaseAnalytics/FirebaseCore.xcframework/ios-i386_x86_64-simulator", - "-F${rootProject.buildDir}/Firebase/FirebaseAnalytics/FirebaseCoreDiagnostics.xcframework/ios-i386_x86_64-simulator", - "-F${rootProject.buildDir}/Firebase/FirebaseAnalytics/FirebaseInstallations.xcframework/ios-i386_x86_64-simulator", - "-F${rootProject.buildDir}/Firebase/FirebaseAnalytics/GoogleDataTransport.xcframework/ios-i386_x86_64-simulator", - "-F${rootProject.buildDir}/Firebase/FirebaseAnalytics/GoogleUtilities.xcframework/ios-i386_x86_64-simulator", - "-F${rootProject.buildDir}/Firebase/FirebaseAnalytics/nanopb.xcframework/ios-i386_x86_64-simulator", - "-F${rootProject.buildDir}/Firebase/FirebaseAnalytics/PromisesObjC.xcframework/ios-i386_x86_64-simulator", - "-F${rootProject.buildDir}/Firebase/FirebaseAnalytics", - "-F${rootProject.buildDir}/Firebase/FirebaseDatabase/FirebaseDatabase.xcframework/ios-i386_x86_64-simulator", - "-F${rootProject.buildDir}/Firebase/FirebaseDatabase/leveldb-library.xcframework/ios-i386_x86_64-simulator" + "-F${rootProject.projectDir}/firebase-app/src/iosMain/c_interop/Carthage/Build/iOS/", + "-F$projectDir/src/iosMain/c_interop/Carthage/Build/iOS/" ) linkerOpts("-ObjC") } @@ -101,9 +93,7 @@ kotlin { val firebaseDatabase by cinterops.creating { packageName("cocoapods.FirebaseDatabase") defFile(file("$projectDir/src/iosMain/c_interop/FirebaseDatabase.def")) - compilerOpts( - "-F${rootProject.buildDir}/Firebase/FirebaseDatabase/FirebaseDatabase.xcframework/ios-i386_x86_64-simulator", - "-F${rootProject.buildDir}/Firebase/FirebaseDatabase/leveldb-library.xcframework/ios-i386_x86_64-simulator") + compilerOpts("-F$projectDir/src/iosMain/c_interop/Carthage/Build/iOS/") } } } diff --git a/firebase-database/src/iosMain/c_interop/Cartfile b/firebase-database/src/iosMain/c_interop/Cartfile new file mode 100644 index 000000000..549180daa --- /dev/null +++ b/firebase-database/src/iosMain/c_interop/Cartfile @@ -0,0 +1 @@ +binary "https://dl.google.com/dl/firebase/ios/carthage/FirebaseDatabaseBinary.json" == 6.30.0 \ No newline at end of file diff --git a/firebase-firestore/build.gradle.kts b/firebase-firestore/build.gradle.kts index 072357d9d..838694430 100644 --- a/firebase-firestore/build.gradle.kts +++ b/firebase-firestore/build.gradle.kts @@ -52,20 +52,8 @@ kotlin { binaries { getTest("DEBUG").apply { linkerOpts( - "-F${rootProject.buildDir}/Firebase/FirebaseAnalytics/FirebaseCore.xcframework/ios-i386_x86_64-simulator", - "-F${rootProject.buildDir}/Firebase/FirebaseAnalytics/FirebaseCoreDiagnostics.xcframework/ios-i386_x86_64-simulator", - "-F${rootProject.buildDir}/Firebase/FirebaseAnalytics/FirebaseInstallations.xcframework/ios-i386_x86_64-simulator", - "-F${rootProject.buildDir}/Firebase/FirebaseAnalytics/GoogleDataTransport.xcframework/ios-i386_x86_64-simulator", - "-F${rootProject.buildDir}/Firebase/FirebaseAnalytics/GoogleUtilities.xcframework/ios-i386_x86_64-simulator", - "-F${rootProject.buildDir}/Firebase/FirebaseAnalytics/nanopb.xcframework/ios-i386_x86_64-simulator", - "-F${rootProject.buildDir}/Firebase/FirebaseAnalytics/PromisesObjC.xcframework/ios-i386_x86_64-simulator", - "-F${rootProject.buildDir}/Firebase/FirebaseAnalytics", - "-F${rootProject.buildDir}/Firebase/FirebaseFirestore/FirebaseFirestore.xcframework/ios-i386_x86_64-simulator", - "-F${rootProject.buildDir}/Firebase/FirebaseFirestore/abseil.xcframework/ios-i386_x86_64-simulator", - "-F${rootProject.buildDir}/Firebase/FirebaseFirestore/BoringSSL-GRPC.xcframework/ios-i386_x86_64-simulator", - "-F${rootProject.buildDir}/Firebase/FirebaseFirestore/gRPC-C++.xcframework/ios-i386_x86_64-simulator", - "-F${rootProject.buildDir}/Firebase/FirebaseFirestore/gRPC-Core.xcframework/ios-i386_x86_64-simulator", - "-F${rootProject.buildDir}/Firebase/FirebaseFirestore/leveldb-library.xcframework/ios-i386_x86_64-simulator" + "-F${rootProject.projectDir}/firebase-app/src/iosMain/c_interop/Carthage/Build/iOS/", + "-F$projectDir/src/iosMain/c_interop/Carthage/Build/iOS/" ) linkerOpts("-ObjC") } @@ -103,14 +91,7 @@ kotlin { val firebasefirestore by cinterops.creating { packageName("cocoapods.FirebaseFirestore") defFile(file("$projectDir/src/iosMain/c_interop/FirebaseFirestore.def")) - compilerOpts( - "-F${rootProject.buildDir}/Firebase/FirebaseFirestore/FirebaseFirestore.xcframework/ios-i386_x86_64-simulator", - "-F${rootProject.buildDir}/Firebase/FirebaseFirestore/abseil.xcframework/ios-i386_x86_64-simulator", - "-F${rootProject.buildDir}/Firebase/FirebaseFirestore/BoringSSL-GRPC.xcframework/ios-i386_x86_64-simulator", - "-F${rootProject.buildDir}/Firebase/FirebaseFirestore/gRPC-C++.xcframework/ios-i386_x86_64-simulator", - "-F${rootProject.buildDir}/Firebase/FirebaseFirestore/gRPC-Core.xcframework/ios-i386_x86_64-simulator", - "-F${rootProject.buildDir}/Firebase/FirebaseFirestore/leveldb-library.xcframework/ios-i386_x86_64-simulator" - ) + compilerOpts("-F$projectDir/src/iosMain/c_interop/Carthage/Build/iOS/") } } } diff --git a/firebase-firestore/src/iosMain/c_interop/Cartfile b/firebase-firestore/src/iosMain/c_interop/Cartfile new file mode 100644 index 000000000..301abee7a --- /dev/null +++ b/firebase-firestore/src/iosMain/c_interop/Cartfile @@ -0,0 +1 @@ +binary "https://dl.google.com/dl/firebase/ios/carthage/FirebaseFirestoreBinary.json" == 6.30.0 \ No newline at end of file diff --git a/firebase-functions/build.gradle.kts b/firebase-functions/build.gradle.kts index d79e1b9fa..06f768388 100644 --- a/firebase-functions/build.gradle.kts +++ b/firebase-functions/build.gradle.kts @@ -50,16 +50,8 @@ kotlin { binaries { getTest("DEBUG").apply { linkerOpts( - "-F${rootProject.buildDir}/Firebase/FirebaseAnalytics/FirebaseCore.xcframework/ios-i386_x86_64-simulator", - "-F${rootProject.buildDir}/Firebase/FirebaseAnalytics/FirebaseCoreDiagnostics.xcframework/ios-i386_x86_64-simulator", - "-F${rootProject.buildDir}/Firebase/FirebaseAnalytics/FirebaseInstallations.xcframework/ios-i386_x86_64-simulator", - "-F${rootProject.buildDir}/Firebase/FirebaseAnalytics/GoogleDataTransport.xcframework/ios-i386_x86_64-simulator", - "-F${rootProject.buildDir}/Firebase/FirebaseAnalytics/GoogleUtilities.xcframework/ios-i386_x86_64-simulator", - "-F${rootProject.buildDir}/Firebase/FirebaseAnalytics/nanopb.xcframework/ios-i386_x86_64-simulator", - "-F${rootProject.buildDir}/Firebase/FirebaseAnalytics/PromisesObjC.xcframework/ios-i386_x86_64-simulator", - "-F${rootProject.buildDir}/Firebase/FirebaseAnalytics", - "-F${rootProject.buildDir}/Firebase/FirebaseFunctions/FirebaseFunctions.xcframework/ios-i386_x86_64-simulator", - "-F${rootProject.buildDir}/Firebase/FirebaseFunctions/GTMSessionFetcher.xcframework/ios-i386_x86_64-simulator" + "-F${rootProject.projectDir}/firebase-app/src/iosMain/c_interop/Carthage/Build/iOS/", + "-F$projectDir/src/iosMain/c_interop/Carthage/Build/iOS/" ) linkerOpts("-ObjC") } @@ -95,9 +87,7 @@ kotlin { val firebasefunctions by cinterops.creating { packageName("cocoapods.FirebaseFunctions") defFile(file("$projectDir/src/iosMain/c_interop/FirebaseFunctions.def")) - compilerOpts( - "-F${rootProject.buildDir}/Firebase/FirebaseFunctions/FirebaseFunctions.xcframework/ios-i386_x86_64-simulator", - "-F${rootProject.buildDir}/Firebase/FirebaseFunctions/GTMSessionFetcher.xcframework/ios-i386_x86_64-simulator") + compilerOpts("-F$projectDir/src/iosMain/c_interop/Carthage/Build/iOS/") } } } diff --git a/firebase-functions/src/iosMain/c_interop/Cartfile b/firebase-functions/src/iosMain/c_interop/Cartfile new file mode 100644 index 000000000..b6ff90411 --- /dev/null +++ b/firebase-functions/src/iosMain/c_interop/Cartfile @@ -0,0 +1 @@ +binary "https://dl.google.com/dl/firebase/ios/carthage/FirebaseFunctionsBinary.json" == 6.30.0 \ No newline at end of file From 9fa36c24fe6e6806741b217e25df86fdb0bd46c4 Mon Sep 17 00:00:00 2001 From: Gijs van Veen Date: Fri, 21 Aug 2020 15:59:18 +0200 Subject: [PATCH 14/32] Track firestore version --- firebase-firestore/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/firebase-firestore/build.gradle.kts b/firebase-firestore/build.gradle.kts index 838694430..08edbefd2 100644 --- a/firebase-firestore/build.gradle.kts +++ b/firebase-firestore/build.gradle.kts @@ -1,4 +1,4 @@ -version = "0.2.0" +version = "0.2.1" plugins { id("com.android.library") From f3fe3db5acc713835189d1ed1361beb7064b61dd Mon Sep 17 00:00:00 2001 From: Gijs van Veen Date: Fri, 21 Aug 2020 16:42:30 +0200 Subject: [PATCH 15/32] Update yaml --- .github/workflows/publish.yml | 15 ++++----------- .github/workflows/pull_request.yml | 15 ++++----------- 2 files changed, 8 insertions(+), 22 deletions(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 09d02418a..f19c050c3 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -24,17 +24,10 @@ jobs: arguments: :updateVersions - name: Grant execute permission for gradlew run: chmod +x gradlew - - name: Retrieve cache key - id: cache-key - uses: actions/cache@v2 - with: - path: build/Firebase-6.17.0.zip - key: key-Firebase-6.17.0 - restore-keys: key-Firebase-6.17.0 - - name: Download Firebase - run: ./gradlew downloadIOSFirebaseZipFile - - name: Expand Zip - run: unzip build/Firebase-6.17.0.zip -d build + - name: Install Homebrew + run: ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" + - name: Install Carthage + run: brew install carthage - name: Publish uses: eskatos/gradle-command-action@v1 with: diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index 07f6ca307..619fb3670 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -20,17 +20,10 @@ jobs: java-version: 1.8 - name: Grant execute permission for gradlew run: chmod +x gradlew - - name: Retrieve cache key - id: cache-key - uses: actions/cache@v2 - with: - path: build/Firebase-6.17.0.zip - key: key-Firebase-6.17.0 - restore-keys: key-Firebase-6.17.0 - - name: Download Firebase - run: ./gradlew downloadIOSFirebaseZipFile - - name: Expand Zip - run: unzip build/Firebase-6.17.0.zip -d build + - name: Install Homebrew + run: ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" + - name: Install Carthage + run: brew install carthage - name: Assemble run: ./gradlew assemble - name: Run JS Tests From 64621ce903d11239545298265ef059eb1742bca8 Mon Sep 17 00:00:00 2001 From: Gijs van Veen Date: Fri, 21 Aug 2020 16:58:22 +0200 Subject: [PATCH 16/32] Remove useless podspec --- firebase-auth/firebase_auth.podspec | 44 ----------------------------- 1 file changed, 44 deletions(-) delete mode 100644 firebase-auth/firebase_auth.podspec diff --git a/firebase-auth/firebase_auth.podspec b/firebase-auth/firebase_auth.podspec deleted file mode 100644 index 21ef430a9..000000000 --- a/firebase-auth/firebase_auth.podspec +++ /dev/null @@ -1,44 +0,0 @@ -Pod::Spec.new do |spec| - spec.name = 'firebase_auth' - spec.version = '0.2.0' - spec.homepage = '' - spec.source = { :git => "Not Published", :tag => "Cocoapods/#{spec.name}/#{spec.version}" } - spec.authors = '' - spec.license = '' - spec.summary = '' - - spec.static_framework = true - spec.vendored_frameworks = "build/cocoapods/framework/firebase_auth.framework" - spec.libraries = "c++" - spec.module_name = "#{spec.name}_umbrella" - - - - spec.pod_target_xcconfig = { - 'KOTLIN_TARGET[sdk=iphonesimulator*]' => 'ios_x64', - 'KOTLIN_TARGET[sdk=iphoneos*]' => 'ios_arm', - 'KOTLIN_TARGET[sdk=watchsimulator*]' => 'watchos_x86', - 'KOTLIN_TARGET[sdk=watchos*]' => 'watchos_arm', - 'KOTLIN_TARGET[sdk=appletvsimulator*]' => 'tvos_x64', - 'KOTLIN_TARGET[sdk=appletvos*]' => 'tvos_arm64', - 'KOTLIN_TARGET[sdk=macosx*]' => 'macos_x64' - } - - spec.script_phases = [ - { - :name => 'Build firebase_auth', - :execution_position => :before_compile, - :shell_path => '/bin/sh', - :script => <<-SCRIPT - set -ev - REPO_ROOT="$PODS_TARGET_SRCROOT" - "$REPO_ROOT/../gradlew" -p "$REPO_ROOT" :firebase-auth:syncFramework \ - -Pkotlin.native.cocoapods.target=$KOTLIN_TARGET \ - -Pkotlin.native.cocoapods.configuration=$CONFIGURATION \ - -Pkotlin.native.cocoapods.cflags="$OTHER_CFLAGS" \ - -Pkotlin.native.cocoapods.paths.headers="$HEADER_SEARCH_PATHS" \ - -Pkotlin.native.cocoapods.paths.frameworks="$FRAMEWORK_SEARCH_PATHS" - SCRIPT - } - ] -end \ No newline at end of file From 1f36fe29d63f707ca4c33a11d62c3a9625c40e41 Mon Sep 17 00:00:00 2001 From: Gijs van Veen Date: Fri, 21 Aug 2020 17:19:31 +0200 Subject: [PATCH 17/32] Code cleanup --- .../gitlive/firebase/firestore/firestore.kt | 40 ++++++++++--------- 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/firebase-firestore/src/iosMain/kotlin/dev/gitlive/firebase/firestore/firestore.kt b/firebase-firestore/src/iosMain/kotlin/dev/gitlive/firebase/firestore/firestore.kt index 36dc19d8a..ce80013fe 100644 --- a/firebase-firestore/src/iosMain/kotlin/dev/gitlive/firebase/firestore/firestore.kt +++ b/firebase-firestore/src/iosMain/kotlin/dev/gitlive/firebase/firestore/firestore.kt @@ -4,7 +4,6 @@ package dev.gitlive.firebase.firestore -import cocoapods.FirebaseCore.FIRApp import cocoapods.FirebaseFirestore.* import kotlinx.cinterop.* import kotlinx.coroutines.CompletableDeferred @@ -24,18 +23,14 @@ actual val Firebase.firestore get() = FirebaseFirestore(FIRFirestore.firestore()) actual fun Firebase.firestore(app: FirebaseApp): FirebaseFirestore { - val firFirestore = FIRFirestore.firestoreForApp(app.ios) - return FirebaseFirestore(firFirestore) + return FirebaseFirestore(FIRFirestore.firestoreForApp(app.ios)) } actual class FirebaseFirestore(val ios: FIRFirestore) { actual fun collection(collectionPath: String) = CollectionReference(ios.collectionWithPath(collectionPath)) - actual fun document(documentPath: String): DocumentReference { - val path = ios.documentWithPath(documentPath) - return DocumentReference(path) - } + actual fun document(documentPath: String) = DocumentReference(ios.documentWithPath(documentPath)) actual fun batch() = WriteBatch(ios.batch()) @@ -140,28 +135,37 @@ actual class DocumentReference(val ios: FIRDocumentReference) { actual val path: String get() = ios.path - actual suspend fun set(data: Any, encodeDefaults: Boolean, merge: Boolean) = await { ios.setData(encode(data, encodeDefaults)!! as Map, merge, it) } + actual suspend fun set(data: Any, encodeDefaults: Boolean, merge: Boolean) = + await { ios.setData(encode(data, encodeDefaults)!! as Map, merge, it) } - actual suspend fun set(data: Any, encodeDefaults: Boolean, vararg mergeFields: String) = await { ios.setData(encode(data, encodeDefaults)!! as Map, mergeFields.asList(), it) } + actual suspend fun set(data: Any, encodeDefaults: Boolean, vararg mergeFields: String) = + await { ios.setData(encode(data, encodeDefaults)!! as Map, mergeFields.asList(), it) } - actual suspend fun set(data: Any, encodeDefaults: Boolean, vararg mergeFieldPaths: FieldPath) = await { ios.setData(encode(data, encodeDefaults)!! as Map, mergeFieldPaths.asList(), it) } + actual suspend fun set(data: Any, encodeDefaults: Boolean, vararg mergeFieldPaths: FieldPath) = + await { ios.setData(encode(data, encodeDefaults)!! as Map, mergeFieldPaths.asList(), it) } - actual suspend fun set(strategy: SerializationStrategy, data: T, encodeDefaults: Boolean, merge: Boolean) = await { ios.setData(encode(strategy, data, encodeDefaults)!! as Map, merge, it) } + actual suspend fun set(strategy: SerializationStrategy, data: T, encodeDefaults: Boolean, merge: Boolean) = + await { ios.setData(encode(strategy, data, encodeDefaults)!! as Map, merge, it) } - actual suspend fun set(strategy: SerializationStrategy, data: T, encodeDefaults: Boolean, vararg mergeFields: String) = await { - ios.setData(encode(strategy, data, encodeDefaults)!! as Map, mergeFields.asList(), it) } + actual suspend fun set(strategy: SerializationStrategy, data: T, encodeDefaults: Boolean, vararg mergeFields: String) = + await { ios.setData(encode(strategy, data, encodeDefaults)!! as Map, mergeFields.asList(), it) } - actual suspend fun set(strategy: SerializationStrategy, data: T, encodeDefaults: Boolean, vararg mergeFieldPaths: FieldPath) = await { ios.setData(encode(strategy, data, encodeDefaults)!! as Map, mergeFieldPaths.asList(), it) } + actual suspend fun set(strategy: SerializationStrategy, data: T, encodeDefaults: Boolean, vararg mergeFieldPaths: FieldPath) = + await { ios.setData(encode(strategy, data, encodeDefaults)!! as Map, mergeFieldPaths.asList(), it) } @Suppress("UNCHECKED_CAST") - actual suspend fun update(data: Any, encodeDefaults: Boolean) = await { ios.updateData(encode(data, encodeDefaults) as Map, it) } + actual suspend fun update(data: Any, encodeDefaults: Boolean) = + await { ios.updateData(encode(data, encodeDefaults) as Map, it) } @Suppress("UNCHECKED_CAST") - actual suspend fun update(strategy: SerializationStrategy, data: T, encodeDefaults: Boolean) = await { ios.updateData(encode(strategy, data, encodeDefaults) as Map, it) } + actual suspend fun update(strategy: SerializationStrategy, data: T, encodeDefaults: Boolean) = + await { ios.updateData(encode(strategy, data, encodeDefaults) as Map, it) } - actual suspend fun update(vararg fieldsAndValues: Pair) = await { block -> ios.updateData(fieldsAndValues.associate { it }, block) } + actual suspend fun update(vararg fieldsAndValues: Pair) = + await { block -> ios.updateData(fieldsAndValues.associate { it }, block) } - actual suspend fun update(vararg fieldsAndValues: Pair) = await { block -> ios.updateData(fieldsAndValues.associate { it }, block) } + actual suspend fun update(vararg fieldsAndValues: Pair) = + await { block -> ios.updateData(fieldsAndValues.associate { it }, block) } actual suspend fun delete() = await { ios.deleteDocumentWithCompletion(it) } From dcbe856c70f59884e149f8e4f9832a3754e34cbd Mon Sep 17 00:00:00 2001 From: Gijs van Veen Date: Wed, 7 Oct 2020 17:17:35 +0200 Subject: [PATCH 18/32] Fixing remarks --- .../kotlin/dev/gitlive/firebase/auth/auth.kt | 63 +++++++------- .../dev/gitlive/firebase/auth/credentials.kt | 48 ++++++----- .../dev/gitlive/firebase/auth/multifactor.kt | 4 +- .../kotlin/dev/gitlive/firebase/auth/user.kt | 40 ++++----- .../kotlin/dev/gitlive/firebase/auth/auth.kt | 37 +++++---- .../dev/gitlive/firebase/auth/credentials.kt | 28 ++++--- .../dev/gitlive/firebase/auth/multifactor.kt | 2 +- .../kotlin/dev/gitlive/firebase/auth/user.kt | 20 ++--- .../kotlin/dev/gitlive/firebase/auth/auth.kt | 62 +++++++------- .../dev/gitlive/firebase/auth/credentials.kt | 26 +++--- .../dev/gitlive/firebase/auth/multifactor.kt | 4 +- .../kotlin/dev/gitlive/firebase/auth/user.kt | 42 +++------- .../kotlin/dev/gitlive/firebase/auth/auth.kt | 82 ++++++++----------- .../dev/gitlive/firebase/auth/credentials.kt | 34 ++++---- .../dev/gitlive/firebase/auth/multifactor.kt | 4 +- .../kotlin/dev/gitlive/firebase/auth/user.kt | 47 +++-------- 16 files changed, 250 insertions(+), 293 deletions(-) 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 ac143346c..7a776d6b1 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 @@ -2,6 +2,7 @@ * Copyright (c) 2020 GitLive Ltd. Use of this source code is governed by the Apache 2.0 license. */ +@file:JvmName("android") package dev.gitlive.firebase.auth import com.google.firebase.auth.ActionCodeEmailInfo @@ -90,12 +91,21 @@ actual class ActionCodeResult(val android: com.google.firebase.auth.ActionCodeRe com.google.firebase.auth.ActionCodeResult.REVERT_SECOND_FACTOR_ADDITION -> Operation.RevertSecondFactorAddition else -> Operation.Error } - actual fun > getData(type: A): T? = when (type) { - is ActionCodeDataType.Email -> android.info?.email - is ActionCodeDataType.PreviousEmail -> (android.info as? ActionCodeEmailInfo)?.previousEmail - is ActionCodeDataType.MultiFactor -> (android.info as? ActionCodeMultiFactorInfo)?.multiFactorInfo?.let { MultiFactorInfo(it) } - else -> null - } as? T +} + +actual sealed class ActionCodeDataType { + + internal actual abstract fun dataForResult(result: ActionCodeResult): T? + + actual object Email : ActionCodeDataType() { + override fun dataForResult(result: ActionCodeResult): String? = result.android.info?.email + } + actual object PreviousEmail : ActionCodeDataType() { + override fun dataForResult(result: ActionCodeResult): String? = (result.android.info as? ActionCodeEmailInfo)?.previousEmail + } + actual object MultiFactor : ActionCodeDataType() { + override fun dataForResult(result: ActionCodeResult): MultiFactorInfo? = (result.android.info as? ActionCodeMultiFactorInfo)?.multiFactorInfo?.let { MultiFactorInfo(it) } + } } actual class SignInMethodQueryResult(val android: com.google.firebase.auth.SignInMethodQueryResult) { @@ -104,33 +114,28 @@ actual class SignInMethodQueryResult(val android: com.google.firebase.auth.SignI } actual class ActionCodeSettings private constructor(val android: com.google.firebase.auth.ActionCodeSettings) { - actual class Builder(val android: com.google.firebase.auth.ActionCodeSettings.Builder = com.google.firebase.auth.ActionCodeSettings.newBuilder()) { - actual fun setAndroidPackageName(androidPackageName: String, installIfNotAvailable: Boolean, minimumVersion: String?): Builder = apply { - android.setAndroidPackageName(androidPackageName, installIfNotAvailable, minimumVersion) - } - actual fun setDynamicLinkDomain(dynamicLinkDomain: String): Builder = apply { - android.setDynamicLinkDomain(dynamicLinkDomain) - } - actual fun setHandleCodeInApp(canHandleCodeInApp: Boolean): Builder = apply { - android.setHandleCodeInApp(canHandleCodeInApp) - } - actual fun setIOSBundleId(iOSBundleId: String): Builder = apply { - android.setIOSBundleId(iOSBundleId) - } - actual fun setUrl(url: String): Builder = apply { - android.setUrl(url) + + actual constructor(url: String, + androidPackageName: AndroidPackageName?, + dynamicLinkDomain: String?, + canHandleCodeInApp: Boolean, + iOSBundleId: String? + ) : this(com.google.firebase.auth.ActionCodeSettings.newBuilder().apply { + this.url = url + androidPackageName?.let { + this.setAndroidPackageName(it.androidPackageName, it.installIfNotAvailable, it.minimumVersion) } - actual fun build(): ActionCodeSettings = ActionCodeSettings(android.build()) - } + this.dynamicLinkDomain = dynamicLinkDomain + this.handleCodeInApp = canHandleCodeInApp + this.iosBundleId = iosBundleId + }.build()) actual val canHandleCodeInApp: Boolean get() = android.canHandleCodeInApp() - actual val androidInstallApp: Boolean - get() = android.androidInstallApp - actual val androidMinimumVersion: String? - get() = android.androidMinimumVersion - actual val androidPackageName: String? - get() = android.androidPackageName + actual val androidPackageName: AndroidPackageName? + get() = android.androidPackageName?.let { + AndroidPackageName(it, android.androidInstallApp, android.androidMinimumVersion) + } actual val iOSBundle: String? get() = android.iosBundle actual val url: String diff --git a/firebase-auth/src/androidMain/kotlin/dev/gitlive/firebase/auth/credentials.kt b/firebase-auth/src/androidMain/kotlin/dev/gitlive/firebase/auth/credentials.kt index 7da683b4c..c1e1340d1 100644 --- a/firebase-auth/src/androidMain/kotlin/dev/gitlive/firebase/auth/credentials.kt +++ b/firebase-auth/src/androidMain/kotlin/dev/gitlive/firebase/auth/credentials.kt @@ -23,46 +23,44 @@ actual class PhoneAuthCredential(override val android: com.google.firebase.auth. actual class OAuthCredential(override val android: com.google.firebase.auth.OAuthCredential) : AuthCredential(android) actual object EmailAuthProvider { - actual fun credentialWithEmail( + actual fun credential( email: String, password: String ): AuthCredential = AuthCredential(com.google.firebase.auth.EmailAuthProvider.getCredential(email, password)) } actual object FacebookAuthProvider { - actual fun credentialWithAccessToken(accessToken: String): AuthCredential = AuthCredential(com.google.firebase.auth.FacebookAuthProvider.getCredential(accessToken)) + actual fun credential(accessToken: String): AuthCredential = AuthCredential(com.google.firebase.auth.FacebookAuthProvider.getCredential(accessToken)) } actual object GithubAuthProvider { - actual fun credentialWithToken(token: String): AuthCredential = AuthCredential(com.google.firebase.auth.GithubAuthProvider.getCredential(token)) + actual fun credential(token: String): AuthCredential = AuthCredential(com.google.firebase.auth.GithubAuthProvider.getCredential(token)) } actual object GoogleAuthProvider { - actual fun credentialWithIDAndAccessToken(idToken: String, accessToken: String): AuthCredential = AuthCredential(com.google.firebase.auth.GoogleAuthProvider.getCredential(idToken, accessToken)) + actual fun credential(idToken: String, accessToken: String): AuthCredential = AuthCredential(com.google.firebase.auth.GoogleAuthProvider.getCredential(idToken, accessToken)) } actual class OAuthProvider(val android: com.google.firebase.auth.OAuthProvider.Builder, private val auth: FirebaseAuth) { actual constructor(provider: String, auth: FirebaseAuth) : this(com.google.firebase.auth.OAuthProvider.newBuilder(provider, auth.android), auth) actual companion object { - actual fun credentialsWithAccessToken(providerId: String, accessToken: String): AuthCredential = createCredentials(providerId) { - this.accessToken = accessToken - } - actual fun credentialsWithIDAndAccessToken(providerId: String, idToken: String, accessToken: String): AuthCredential = createCredentials(providerId) { - setIdToken(idToken) - this.accessToken = accessToken - } - actual fun credentialsWithIDRawNonceAndAccessToken(providerId: String, idToken: String, rawNonce: String, accessToken: String): AuthCredential = createCredentials(providerId) { - setIdTokenWithRawNonce(idToken, rawNonce) - this.accessToken = accessToken - } - actual fun credentialsWithIDAndRawNonce(providerId: String, idToken: String, rawNonce: String): AuthCredential = createCredentials(providerId) { - setIdTokenWithRawNonce(idToken, rawNonce) - } - - private fun createCredentials(providerId: String, block: com.google.firebase.auth.OAuthProvider.CredentialBuilder.() -> Unit): AuthCredential { - val credential = com.google.firebase.auth.OAuthProvider.newCredentialBuilder(providerId).apply { - block() + actual fun credentials(type: OAuthCredentialsType): AuthCredential { + val credential = com.google.firebase.auth.OAuthProvider.newCredentialBuilder(type.providerId).apply { + when (type) { + is OAuthCredentialsType.AccessToken -> accessToken = type.accessToken + is OAuthCredentialsType.IdAndAccessToken -> { + accessToken = type.accessToken + setIdToken(type.idToken) + } + is OAuthCredentialsType.IdAndAccessTokenAndRawNonce -> { + accessToken = type.accessToken + setIdTokenWithRawNonce(type.idToken, type.rawNonce) + } + is OAuthCredentialsType.IdTokenAndRawNonce -> { + setIdTokenWithRawNonce(type.idToken, type.rawNonce) + } + } }.build() return (credential as? com.google.firebase.auth.OAuthCredential)?.let { OAuthCredential(it) } ?: AuthCredential(credential) } @@ -87,7 +85,7 @@ actual class PhoneAuthProvider(val android: com.google.firebase.auth.PhoneAuthPr actual constructor(auth: FirebaseAuth) : this(com.google.firebase.auth.PhoneAuthProvider.getInstance(auth.android)) - actual fun credentialWithVerificationIdAndSmsCode(verificationId: String, smsCode: String): PhoneAuthCredential = PhoneAuthCredential(com.google.firebase.auth.PhoneAuthProvider.getCredential(verificationId, smsCode)) + actual fun credential(verificationId: String, smsCode: String): PhoneAuthCredential = PhoneAuthCredential(com.google.firebase.auth.PhoneAuthProvider.getCredential(verificationId, smsCode)) actual suspend fun verifyPhoneNumber(phoneNumber: String, verificationProvider: PhoneVerificationProvider): AuthCredential = coroutineScope { val response = CompletableDeferred>() val callback = object : @@ -102,7 +100,7 @@ actual class PhoneAuthProvider(val android: com.google.firebase.auth.PhoneAuthPr val code = verificationProvider.getVerificationCode() try { val credentials = - credentialWithVerificationIdAndSmsCode(verificationId, code) + credential(verificationId, code) response.complete(Result.success(credentials)) } catch (e: Exception) { response.complete(Result.failure(e)) @@ -134,5 +132,5 @@ actual interface PhoneVerificationProvider { } actual object TwitterAuthProvider { - actual fun credentialWithTokenAndSecret(token: String, secret: String): AuthCredential = AuthCredential(com.google.firebase.auth.TwitterAuthProvider.getCredential(token, secret)) + actual fun credential(token: String, secret: String): AuthCredential = AuthCredential(com.google.firebase.auth.TwitterAuthProvider.getCredential(token, secret)) } diff --git a/firebase-auth/src/androidMain/kotlin/dev/gitlive/firebase/auth/multifactor.kt b/firebase-auth/src/androidMain/kotlin/dev/gitlive/firebase/auth/multifactor.kt index 7721cc175..7b68960c2 100644 --- a/firebase-auth/src/androidMain/kotlin/dev/gitlive/firebase/auth/multifactor.kt +++ b/firebase-auth/src/androidMain/kotlin/dev/gitlive/firebase/auth/multifactor.kt @@ -18,8 +18,8 @@ actual class MultiFactor(val android: com.google.firebase.auth.MultiFactor) { actual class MultiFactorInfo(val android: com.google.firebase.auth.MultiFactorInfo) { actual val displayName: String? get() = android.displayName - actual val enrollmentTime: Long - get() = android.enrollmentTimestamp + actual val enrollmentTime: Double + get() = android.enrollmentTimestamp.toDouble() actual val factorId: String get() = android.factorId actual val uid: String diff --git a/firebase-auth/src/androidMain/kotlin/dev/gitlive/firebase/auth/user.kt b/firebase-auth/src/androidMain/kotlin/dev/gitlive/firebase/auth/user.kt index 77802efef..20aa61055 100644 --- a/firebase-auth/src/androidMain/kotlin/dev/gitlive/firebase/auth/user.kt +++ b/firebase-auth/src/androidMain/kotlin/dev/gitlive/firebase/auth/user.kt @@ -5,6 +5,7 @@ package dev.gitlive.firebase.auth import android.net.Uri +import com.google.firebase.auth.UserProfileChangeRequest import kotlinx.coroutines.tasks.await actual class FirebaseUser internal constructor(val android: com.google.firebase.auth.FirebaseUser) { @@ -22,8 +23,8 @@ actual class FirebaseUser internal constructor(val android: com.google.firebase. get() = android.isAnonymous actual val isEmailVerified: Boolean get() = android.isEmailVerified - actual val metaData: MetaData? - get() = android.metadata?.let{ MetaData(it) } + actual val metaData: UserMetaData? + get() = android.metadata?.let{ UserMetaData(it) } actual val multiFactor: MultiFactor get() = MultiFactor(android.multiFactor) actual val providerData: List @@ -44,9 +45,12 @@ actual class FirebaseUser internal constructor(val android: com.google.firebase. actual suspend fun updateEmail(email: String) = android.updateEmail(email).await().run { Unit } actual suspend fun updatePassword(password: String) = android.updatePassword(password).await().run { Unit } actual suspend fun updatePhoneNumber(credential: PhoneAuthCredential) = android.updatePhoneNumber(credential.android).await().run { Unit } - actual suspend fun updateProfile(buildRequest: UserProfileChangeRequest.Builder.() -> Unit) { - val request = UserProfileChangeRequest.Builder().apply(buildRequest).build() - android.updateProfile(request.android).await() + actual suspend fun updateProfile(displayName: String?, photoUrl: String?) { + val request = UserProfileChangeRequest.Builder().apply { + this.displayName = displayName + photoUri = photoURL?.let { Uri.parse(it) } + }.build() + android.updateProfile(request).await() } actual suspend fun verifyBeforeUpdateEmail(newEmail: String, actionCodeSettings: ActionCodeSettings?) = android.verifyBeforeUpdateEmail(newEmail, actionCodeSettings?.android).await().run { Unit } } @@ -66,25 +70,9 @@ actual class UserInfo(val android: com.google.firebase.auth.UserInfo) { get() = android.uid } -actual class MetaData(val android: com.google.firebase.auth.FirebaseUserMetadata) { - actual val creationTime: Long? - get() = android.creationTimestamp - actual val lastSignInTime: Long? - get() = android.lastSignInTimestamp -} - -actual class UserProfileChangeRequest(val android: com.google.firebase.auth.UserProfileChangeRequest) { - actual class Builder(val android: com.google.firebase.auth.UserProfileChangeRequest.Builder = com.google.firebase.auth.UserProfileChangeRequest.Builder()) { - actual fun setDisplayName(displayName: String?): Builder = apply { - android.setDisplayName(displayName) - } - actual fun setPhotoURL(photoURL: String?): Builder = apply { - android.setPhotoUri(photoURL?.let { Uri.parse(it) }) - } - actual fun build(): UserProfileChangeRequest = UserProfileChangeRequest(android.build()) - } - actual val displayName: String? - get() = android.displayName - actual val photoURL: String? - get() = android.photoUri?.toString() +actual class UserMetaData(val android: com.google.firebase.auth.FirebaseUserMetadata) { + actual val creationTime: Double? + get() = android.creationTimestamp.toDouble() + actual val lastSignInTime: Double? + get() = android.lastSignInTimestamp.toDouble() } 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 7414b0845..c8d04f224 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 @@ -42,7 +42,10 @@ expect class AuthResult { expect class ActionCodeResult { val operation: Operation - fun > getData(type: A): T? +} + +fun > ActionCodeResult.getData(type: A): T? { + return type.dataForResult(this) } expect class SignInMethodQueryResult { @@ -59,30 +62,32 @@ enum class Operation { RevertSecondFactorAddition } -sealed class ActionCodeDataType { - object Email : ActionCodeDataType() - object PreviousEmail : ActionCodeDataType() - object MultiFactor : ActionCodeDataType() +expect sealed class ActionCodeDataType { + + internal abstract fun dataForResult(result: ActionCodeResult): T? + + object Email : ActionCodeDataType + object PreviousEmail : ActionCodeDataType + object MultiFactor : ActionCodeDataType } expect class ActionCodeSettings { - class Builder { - fun setAndroidPackageName(androidPackageName: String, installIfNotAvailable: Boolean, minimumVersion: String?): Builder - fun setDynamicLinkDomain(dynamicLinkDomain: String): Builder - fun setHandleCodeInApp(canHandleCodeInApp: Boolean): Builder - fun setIOSBundleId(iOSBundleId: String): Builder - fun setUrl(url: String): Builder - fun build(): ActionCodeSettings - } + constructor( + url: String, + androidPackageName: AndroidPackageName? = null, + dynamicLinkDomain: String? = null, + canHandleCodeInApp: Boolean = false, + iOSBundleId: String? = null + ) val canHandleCodeInApp: Boolean - val androidInstallApp: Boolean - val androidMinimumVersion: String? - val androidPackageName: String? + val androidPackageName: AndroidPackageName? val iOSBundle: String? val url: String } +data class AndroidPackageName(val androidPackageName: String, val installIfNotAvailable: Boolean, val minimumVersion: String?) + expect open class FirebaseAuthException : FirebaseException expect class FirebaseAuthActionCodeException : FirebaseAuthException expect class FirebaseAuthEmailException : FirebaseAuthException diff --git a/firebase-auth/src/commonMain/kotlin/dev/gitlive/firebase/auth/credentials.kt b/firebase-auth/src/commonMain/kotlin/dev/gitlive/firebase/auth/credentials.kt index c0d88a703..6146f5348 100644 --- a/firebase-auth/src/commonMain/kotlin/dev/gitlive/firebase/auth/credentials.kt +++ b/firebase-auth/src/commonMain/kotlin/dev/gitlive/firebase/auth/credentials.kt @@ -5,6 +5,8 @@ package dev.gitlive.firebase.auth import dev.gitlive.firebase.Firebase +import kotlin.jvm.JvmName +import kotlin.js.JsName expect open class AuthCredential { val providerId: String @@ -14,27 +16,33 @@ expect class PhoneAuthCredential : AuthCredential expect class OAuthCredential : AuthCredential expect object EmailAuthProvider { - fun credentialWithEmail(email: String, password: String): AuthCredential + fun credential(email: String, password: String): AuthCredential } expect object FacebookAuthProvider { - fun credentialWithAccessToken(accessToken: String): AuthCredential + fun credential(accessToken: String): AuthCredential } expect object GithubAuthProvider { - fun credentialWithToken(token: String): AuthCredential + fun credential(token: String): AuthCredential } expect object GoogleAuthProvider { - fun credentialWithIDAndAccessToken(idToken: String, accessToken: String): AuthCredential + fun credential(idToken: String, accessToken: String): AuthCredential +} + +sealed class OAuthCredentialsType { + abstract val providerId: String + data class AccessToken(val accessToken: String, override val providerId: String) : OAuthCredentialsType() + data class IdAndAccessToken(val idToken: String, val accessToken: String, override val providerId: String) : OAuthCredentialsType() + data class IdAndAccessTokenAndRawNonce(val idToken: String, val accessToken: String, val rawNonce: String, override val providerId: String) : OAuthCredentialsType() + data class IdTokenAndRawNonce(val idToken: String, val rawNonce: String, override val providerId: String) : OAuthCredentialsType() + } expect class OAuthProvider constructor(provider: String, auth: FirebaseAuth = Firebase.auth) { companion object { - fun credentialsWithAccessToken(providerId: String, accessToken: String): AuthCredential - fun credentialsWithIDAndAccessToken(providerId: String, idToken: String, accessToken: String): AuthCredential - fun credentialsWithIDRawNonceAndAccessToken(providerId: String, idToken: String, rawNonce: String, accessToken: String): AuthCredential - fun credentialsWithIDAndRawNonce(providerId: String, idToken: String, rawNonce: String): AuthCredential + fun credentials(type: OAuthCredentialsType): AuthCredential } fun addScope(vararg scope: String) @@ -46,7 +54,7 @@ expect class OAuthProvider constructor(provider: String, auth: FirebaseAuth = Fi expect class SignInProvider expect class PhoneAuthProvider constructor(auth: FirebaseAuth = Firebase.auth) { - fun credentialWithVerificationIdAndSmsCode(verificationId: String, smsCode: String): PhoneAuthCredential + fun credential(verificationId: String, smsCode: String): PhoneAuthCredential suspend fun verifyPhoneNumber(phoneNumber: String, verificationProvider: PhoneVerificationProvider): AuthCredential } @@ -54,5 +62,5 @@ expect class PhoneAuthProvider constructor(auth: FirebaseAuth = Firebase.auth) { expect interface PhoneVerificationProvider expect object TwitterAuthProvider { - fun credentialWithTokenAndSecret(token: String, secret: String): AuthCredential + fun credential(token: String, secret: String): AuthCredential } diff --git a/firebase-auth/src/commonMain/kotlin/dev/gitlive/firebase/auth/multifactor.kt b/firebase-auth/src/commonMain/kotlin/dev/gitlive/firebase/auth/multifactor.kt index 487fd8124..04d3b11aa 100644 --- a/firebase-auth/src/commonMain/kotlin/dev/gitlive/firebase/auth/multifactor.kt +++ b/firebase-auth/src/commonMain/kotlin/dev/gitlive/firebase/auth/multifactor.kt @@ -14,7 +14,7 @@ expect class MultiFactor { expect class MultiFactorInfo { val displayName: String? - val enrollmentTime: Long + val enrollmentTime: Double val factorId: String val uid: String } diff --git a/firebase-auth/src/commonMain/kotlin/dev/gitlive/firebase/auth/user.kt b/firebase-auth/src/commonMain/kotlin/dev/gitlive/firebase/auth/user.kt index 7804eb881..56e749eea 100644 --- a/firebase-auth/src/commonMain/kotlin/dev/gitlive/firebase/auth/user.kt +++ b/firebase-auth/src/commonMain/kotlin/dev/gitlive/firebase/auth/user.kt @@ -12,7 +12,7 @@ expect class FirebaseUser { val photoURL: String? val isAnonymous: Boolean val isEmailVerified: Boolean - val metaData: MetaData? + val metaData: UserMetaData? val multiFactor: MultiFactor val providerData: List val providerId: String @@ -27,7 +27,7 @@ expect class FirebaseUser { suspend fun updateEmail(email: String) suspend fun updatePassword(password: String) suspend fun updatePhoneNumber(credential: PhoneAuthCredential) - suspend fun updateProfile(buildRequest: UserProfileChangeRequest.Builder.() -> Unit) + suspend fun updateProfile(displayName: String? = null, photoUrl: String? = null) suspend fun verifyBeforeUpdateEmail(newEmail: String, actionCodeSettings: ActionCodeSettings? = null) } @@ -40,17 +40,7 @@ expect class UserInfo { val uid: String } -expect class MetaData { - val creationTime: Long? - val lastSignInTime: Long? -} - -expect class UserProfileChangeRequest { - class Builder { - fun setDisplayName(displayName: String?): Builder - fun setPhotoURL(photoURL: String?): Builder - fun build(): UserProfileChangeRequest - } - val displayName: String? - val photoURL: String? +expect class UserMetaData { + val creationTime: Double? + val lastSignInTime: Double? } 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 e753a37be..df515127b 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 @@ -93,44 +93,48 @@ actual class ActionCodeResult(val ios: FIRActionCodeInfo) { FIRActionCodeOperationRevertSecondFactorAddition -> Operation.RevertSecondFactorAddition else -> Operation.Error } - actual fun > getData(type: A): T? = when (type) { - is ActionCodeDataType.Email -> ios.email - is ActionCodeDataType.PreviousEmail -> ios.previousEmail - is ActionCodeDataType.MultiFactor -> null - else -> null - } as? T +} + +actual sealed class ActionCodeDataType { + + internal actual abstract fun dataForResult(result: ActionCodeResult): T? + + actual object Email : ActionCodeDataType() { + override fun dataForResult(result: ActionCodeResult): String? = result.ios.email + } + actual object PreviousEmail : ActionCodeDataType() { + override fun dataForResult(result: ActionCodeResult): String? = result.ios.previousEmail + } + actual object MultiFactor : ActionCodeDataType() { + override fun dataForResult(result: ActionCodeResult): MultiFactorInfo? = null + } } actual class SignInMethodQueryResult(actual val signInMethods: List) actual class ActionCodeSettings private constructor(val ios: FIRActionCodeSettings) { - actual class Builder(val ios: FIRActionCodeSettings = FIRActionCodeSettings()) { - actual fun setAndroidPackageName(androidPackageName: String, installIfNotAvailable: Boolean, minimumVersion: String?): Builder = apply { - ios.setAndroidPackageName(androidPackageName, installIfNotAvailable, minimumVersion) - } - actual fun setDynamicLinkDomain(dynamicLinkDomain: String): Builder = apply { - ios.setDynamicLinkDomain(dynamicLinkDomain) - } - actual fun setHandleCodeInApp(canHandleCodeInApp: Boolean): Builder = apply { - ios.setHandleCodeInApp(canHandleCodeInApp) - } - actual fun setIOSBundleId(iOSBundleId: String): Builder = apply { - ios.setIOSBundleID(iOSBundleId) - } - actual fun setUrl(url: String): Builder = apply { - ios.setURL(NSURL.URLWithString(url)) + + actual constructor(url: String, + androidPackageName: AndroidPackageName?, + dynamicLinkDomain: String?, + canHandleCodeInApp: Boolean, + iOSBundleId: String? + ) : this(FIRActionCodeSettings().apply { + this.URL = NSURL.URLWithString(url) + androidPackageName?.let { + this.setAndroidPackageName(it.androidPackageName, it.installIfNotAvailable, it.minimumVersion) } - actual fun build(): ActionCodeSettings = ActionCodeSettings(ios) - } + this.dynamicLinkDomain = dynamicLinkDomain + this.handleCodeInApp = canHandleCodeInApp + iOSBundleId?.let { setIOSBundleID(it) } + }) actual val canHandleCodeInApp: Boolean get() = ios.handleCodeInApp() - actual val androidInstallApp: Boolean - get() = ios.androidInstallIfNotAvailable - actual val androidMinimumVersion: String? - get() = ios.androidMinimumVersion - actual val androidPackageName: String? - get() = ios.androidPackageName + actual val androidPackageName: AndroidPackageName? + get() = ios.androidPackageName?.let { + AndroidPackageName(it, ios.androidInstallIfNotAvailable, ios.androidMinimumVersion) + } actual val iOSBundle: String? get() = ios.iOSBundleID actual val url: String diff --git a/firebase-auth/src/iosMain/kotlin/dev/gitlive/firebase/auth/credentials.kt b/firebase-auth/src/iosMain/kotlin/dev/gitlive/firebase/auth/credentials.kt index 8be084064..88b8312cf 100644 --- a/firebase-auth/src/iosMain/kotlin/dev/gitlive/firebase/auth/credentials.kt +++ b/firebase-auth/src/iosMain/kotlin/dev/gitlive/firebase/auth/credentials.kt @@ -15,7 +15,7 @@ actual class PhoneAuthCredential(override val ios: FIRPhoneAuthCredential) : Aut actual class OAuthCredential(override val ios: FIROAuthCredential) : AuthCredential(ios) actual object EmailAuthProvider { - actual fun credentialWithEmail( + actual fun credential( email: String, password: String ): AuthCredential = @@ -23,25 +23,29 @@ actual object EmailAuthProvider { } actual object FacebookAuthProvider { - actual fun credentialWithAccessToken(accessToken: String): AuthCredential = AuthCredential(FIRFacebookAuthProvider.credentialWithAccessToken(accessToken)) + actual fun credential(accessToken: String): AuthCredential = AuthCredential(FIRFacebookAuthProvider.credentialWithAccessToken(accessToken)) } actual object GithubAuthProvider { - actual fun credentialWithToken(token: String): AuthCredential = AuthCredential(FIRGitHubAuthProvider.credentialWithToken(token)) + actual fun credential(token: String): AuthCredential = AuthCredential(FIRGitHubAuthProvider.credentialWithToken(token)) } actual object GoogleAuthProvider { - actual fun credentialWithIDAndAccessToken(idToken: String, accessToken: String): AuthCredential = AuthCredential(FIRGoogleAuthProvider.credentialWithIDToken(idToken, accessToken)) + actual fun credential(idToken: String, accessToken: String): AuthCredential = AuthCredential(FIRGoogleAuthProvider.credentialWithIDToken(idToken, accessToken)) } actual class OAuthProvider(val ios: FIROAuthProvider, private val auth: FirebaseAuth) { actual constructor(provider: String, auth: FirebaseAuth) : this(FIROAuthProvider.providerWithProviderID(provider, auth.ios), auth) actual companion object { - actual fun credentialsWithAccessToken(providerId: String, accessToken: String): AuthCredential = AuthCredential(FIROAuthProvider.credentialWithProviderID(providerId, accessToken)) - actual fun credentialsWithIDAndAccessToken(providerId: String, idToken: String, accessToken: String): AuthCredential = AuthCredential(FIROAuthProvider.credentialWithProviderID(providerID = providerId, IDToken = idToken, accessToken = accessToken)) - actual fun credentialsWithIDRawNonceAndAccessToken(providerId: String, idToken: String, rawNonce: String, accessToken: String): AuthCredential = AuthCredential(FIROAuthProvider.credentialWithProviderID(providerID = providerId, IDToken = idToken, rawNonce = rawNonce, accessToken = accessToken)) - actual fun credentialsWithIDAndRawNonce(providerId: String, idToken: String, rawNonce: String): AuthCredential = AuthCredential(FIROAuthProvider.credentialWithProviderID(providerID = providerId, IDToken = idToken, rawNonce = rawNonce)) + actual fun credentials(type: OAuthCredentialsType): AuthCredential { + return AuthCredential(when (type) { + is OAuthCredentialsType.AccessToken -> FIROAuthProvider.credentialWithProviderID(type.providerId, type.accessToken) + is OAuthCredentialsType.IdAndAccessToken -> FIROAuthProvider.credentialWithProviderID(providerID = type.providerId, IDToken = type.idToken, accessToken = type.accessToken) + is OAuthCredentialsType.IdAndAccessTokenAndRawNonce -> FIROAuthProvider.credentialWithProviderID(providerID = type.providerId, IDToken = type.idToken, rawNonce = type.rawNonce, accessToken = type.accessToken) + is OAuthCredentialsType.IdTokenAndRawNonce -> FIROAuthProvider.credentialWithProviderID(providerID = type.providerId, IDToken = type.idToken, rawNonce = type.rawNonce) + }) + } } actual fun addScope(vararg scope: String) { @@ -72,11 +76,11 @@ actual class PhoneAuthProvider(val ios: FIRPhoneAuthProvider) { actual constructor(auth: FirebaseAuth) : this(FIRPhoneAuthProvider.providerWithAuth(auth.ios)) - actual fun credentialWithVerificationIdAndSmsCode(verificationId: String, smsCode: String): PhoneAuthCredential = PhoneAuthCredential(ios.credentialWithVerificationID(verificationId, smsCode)) + actual fun credential(verificationId: String, smsCode: String): PhoneAuthCredential = PhoneAuthCredential(ios.credentialWithVerificationID(verificationId, smsCode)) actual suspend fun verifyPhoneNumber(phoneNumber: String, verificationProvider: PhoneVerificationProvider): AuthCredential { val verificationId: String = ios.awaitExpectedResult { ios.verifyPhoneNumber(phoneNumber, verificationProvider.delegate, it) } val verificationCode = verificationProvider.getVerificationCode() - return credentialWithVerificationIdAndSmsCode(verificationId, verificationCode) + return credential(verificationId, verificationCode) } } @@ -86,5 +90,5 @@ actual interface PhoneVerificationProvider { } actual object TwitterAuthProvider { - actual fun credentialWithTokenAndSecret(token: String, secret: String): AuthCredential = AuthCredential(FIRTwitterAuthProvider.credentialWithToken(token, secret)) + actual fun credential(token: String, secret: String): AuthCredential = AuthCredential(FIRTwitterAuthProvider.credentialWithToken(token, secret)) } \ No newline at end of file diff --git a/firebase-auth/src/iosMain/kotlin/dev/gitlive/firebase/auth/multifactor.kt b/firebase-auth/src/iosMain/kotlin/dev/gitlive/firebase/auth/multifactor.kt index 55942b98e..add3a8e98 100644 --- a/firebase-auth/src/iosMain/kotlin/dev/gitlive/firebase/auth/multifactor.kt +++ b/firebase-auth/src/iosMain/kotlin/dev/gitlive/firebase/auth/multifactor.kt @@ -18,8 +18,8 @@ actual class MultiFactor(val ios: FIRMultiFactor) { actual class MultiFactorInfo(val ios: FIRMultiFactorInfo) { actual val displayName: String? get() = ios.displayName - actual val enrollmentTime: Long - get() = ios.enrollmentDate.timeIntervalSinceReferenceDate.toLong() + actual val enrollmentTime: Double + get() = ios.enrollmentDate.timeIntervalSinceReferenceDate.toDouble() actual val factorId: String get() = ios.factorID actual val uid: String diff --git a/firebase-auth/src/iosMain/kotlin/dev/gitlive/firebase/auth/user.kt b/firebase-auth/src/iosMain/kotlin/dev/gitlive/firebase/auth/user.kt index 52345d783..1432cd749 100644 --- a/firebase-auth/src/iosMain/kotlin/dev/gitlive/firebase/auth/user.kt +++ b/firebase-auth/src/iosMain/kotlin/dev/gitlive/firebase/auth/user.kt @@ -22,8 +22,8 @@ actual class FirebaseUser internal constructor(val ios: FIRUser) { get() = ios.anonymous actual val isEmailVerified: Boolean get() = ios.emailVerified - actual val metaData: MetaData? - get() = MetaData(ios.metadata) + actual val metaData: UserMetaData? + get() = UserMetaData(ios.metadata) actual val multiFactor: MultiFactor get() = MultiFactor(ios.multiFactor) actual val providerData: List @@ -51,9 +51,12 @@ actual class FirebaseUser internal constructor(val ios: FIRUser) { actual suspend fun updateEmail(email: String) = ios.await { updateEmail(email, it) }.run { Unit } actual suspend fun updatePassword(password: String) = ios.await { updatePassword(password, it) }.run { Unit } actual suspend fun updatePhoneNumber(credential: PhoneAuthCredential) = ios.await { updatePhoneNumberCredential(credential.ios, it) }.run { Unit } - actual suspend fun updateProfile(buildRequest: UserProfileChangeRequest.Builder.() -> Unit) { - val request = UserProfileChangeRequest.Builder(this.ios).apply(buildRequest).build() - ios.await { request.ios.commitChangesWithCompletion(it) } + actual suspend fun updateProfile(displayName: String?, photoUrl: String?) { + val request = ios.profileChangeRequest().apply { + this.displayName = displayName + this.photoURL = photoUrl?.let { NSURL.URLWithString(it) } + } + ios.await { request.commitChangesWithCompletion(it) } } actual suspend fun verifyBeforeUpdateEmail(newEmail: String, actionCodeSettings: ActionCodeSettings?) = ios.await { actionCodeSettings?.let { actionSettings -> sendEmailVerificationBeforeUpdatingEmail(newEmail, actionSettings.ios, it) } ?: sendEmailVerificationBeforeUpdatingEmail(newEmail, it) @@ -75,28 +78,9 @@ actual class UserInfo(val ios: FIRUserInfoProtocol) { get() = ios.uid } -actual class MetaData(val ios: FIRUserMetadata) { - actual val creationTime: Long? - get() = ios.creationDate?.timeIntervalSinceReferenceDate?.toLong() - actual val lastSignInTime: Long? - get() = ios.lastSignInDate?.timeIntervalSinceReferenceDate?.toLong() -} - -actual class UserProfileChangeRequest(val ios: FIRUserProfileChangeRequest) { - actual class Builder(private val user: FIRUser) { - - private val request = user.profileChangeRequest() - - actual fun setDisplayName(displayName: String?): Builder = apply { - request.setDisplayName(displayName) - } - actual fun setPhotoURL(photoURL: String?): Builder = apply { - request.setPhotoURL(photoURL?.let { NSURL.URLWithString(it) }) - } - actual fun build(): UserProfileChangeRequest = UserProfileChangeRequest(request) - } - actual val displayName: String? - get() = ios.displayName - actual val photoURL: String? - get() = ios.photoURL?.absoluteString +actual class UserMetaData(val ios: FIRUserMetadata) { + actual val creationTime: Double? + get() = ios.creationDate?.timeIntervalSinceReferenceDate?.toDouble() + actual val lastSignInTime: Double? + get() = ios.lastSignInDate?.timeIntervalSinceReferenceDate?.toDouble() } 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 2483a8bee..14b65046d 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 @@ -94,66 +94,54 @@ actual class ActionCodeResult(val js: firebase.auth.ActionCodeInfo) { "REVERT_SECOND_FACTOR_ADDITION" -> Operation.RevertSecondFactorAddition else -> Operation.Error } - actual fun > getData(type: A): T? = when (type) { - is ActionCodeDataType.Email -> js.data.email - is ActionCodeDataType.PreviousEmail -> js.data.previousEmail - is ActionCodeDataType.MultiFactor -> js.data.multiFactorInfo - else -> null - } as? T } -actual class SignInMethodQueryResult(actual val signInMethods: List) +actual sealed class ActionCodeDataType { -actual class ActionCodeSettings private constructor(val js: firebase.auth.ActionCodeSettings) { - actual class Builder(private var url: String) { + internal actual abstract fun dataForResult(result: ActionCodeResult): T? - private var androidSettings: firebase.auth.AndroidActionCodeSettings? = null - private var dynamicLinkDomain: String? = null - private var handleCodeInApp: Boolean? = null - private var iOS: firebase.auth.iOSActionCodeSettings? = null + actual object Email : ActionCodeDataType() { + override fun dataForResult(result: ActionCodeResult): String? = result.js.data.email + } + actual object PreviousEmail : ActionCodeDataType() { + override fun dataForResult(result: ActionCodeResult): String? = result.js.data.previousEmail + } + actual object MultiFactor : ActionCodeDataType() { + override fun dataForResult(result: ActionCodeResult): MultiFactorInfo? = result.js.data.multiFactorInfo?.let { MultiFactorInfo(it) } + } +} - actual fun setAndroidPackageName(androidPackageName: String, installIfNotAvailable: Boolean, minimumVersion: String?): Builder = apply { - androidSettings = object : firebase.auth.AndroidActionCodeSettings { - override val installApp: Boolean get() = installIfNotAvailable - override val minimumVersion: String? get() = minimumVersion - override val packageName: String get() = androidPackageName +actual class SignInMethodQueryResult(actual val signInMethods: List) - } - } - actual fun setDynamicLinkDomain(dynamicLinkDomain: String): Builder = apply { - this.dynamicLinkDomain = dynamicLinkDomain - } - actual fun setHandleCodeInApp(canHandleCodeInApp: Boolean): Builder = apply { - this.handleCodeInApp = canHandleCodeInApp - } - actual fun setIOSBundleId(iOSBundleId: String): Builder = apply { - iOS = object : firebase.auth.iOSActionCodeSettings { +actual class ActionCodeSettings private constructor(val js: firebase.auth.ActionCodeSettings) { + + actual constructor(url: String, + androidPackageName: AndroidPackageName?, + dynamicLinkDomain: String?, + canHandleCodeInApp: Boolean, + iOSBundleId: String? + ) : this(object : firebase.auth.ActionCodeSettings { + override val android: firebase.auth.AndroidActionCodeSettings? = androidPackageName?.let { androidPackageName -> object : firebase.auth.AndroidActionCodeSettings { + override val installApp: Boolean get() = androidPackageName.installIfNotAvailable + override val minimumVersion: String? get() = androidPackageName.minimumVersion + override val packageName: String get() = androidPackageName.androidPackageName + + } } + override val dynamicLinkDomain: String? = dynamicLinkDomain + override val handleCodeInApp: Boolean? = canHandleCodeInApp + override val iOS: firebase.auth.iOSActionCodeSettings? = iOSBundleId?.let { iOSBundleId -> + object : firebase.auth.iOSActionCodeSettings { override val bundleId: String? get() = iOSBundleId } } - actual fun setUrl(url: String): Builder = apply { - this.url = url - } - actual fun build(): ActionCodeSettings { - return ActionCodeSettings(object : firebase.auth.ActionCodeSettings { - override val android: firebase.auth.AndroidActionCodeSettings? = this@Builder.androidSettings - override val dynamicLinkDomain: String? = this@Builder.dynamicLinkDomain - override val handleCodeInApp: Boolean? = this@Builder.handleCodeInApp - override val iOS: firebase.auth.iOSActionCodeSettings? = this@Builder.iOS - override val url: String = this@Builder.url - }) - } - } + override val url: String = url + }) actual val canHandleCodeInApp: Boolean get() = js.handleCodeInApp ?: false - actual val androidInstallApp: Boolean - get() = js.android?.installApp ?: false - actual val androidMinimumVersion: String? - get() = js.android?.minimumVersion - actual val androidPackageName: String? - get() = js.android?.packageName + actual val androidPackageName: AndroidPackageName? + get() = js.android?.let { AndroidPackageName(it.packageName, it.installApp ?: false, it.minimumVersion) } actual val iOSBundle: String? get() = js.iOS?.bundleId actual val url: String diff --git a/firebase-auth/src/jsMain/kotlin/dev/gitlive/firebase/auth/credentials.kt b/firebase-auth/src/jsMain/kotlin/dev/gitlive/firebase/auth/credentials.kt index ec79ef921..09ce0c990 100644 --- a/firebase-auth/src/jsMain/kotlin/dev/gitlive/firebase/auth/credentials.kt +++ b/firebase-auth/src/jsMain/kotlin/dev/gitlive/firebase/auth/credentials.kt @@ -3,7 +3,6 @@ package dev.gitlive.firebase.auth import dev.gitlive.firebase.firebase import kotlinx.coroutines.await - actual open class AuthCredential(val js: firebase.auth.AuthCredential) { actual val providerId: String get() = js.providerId @@ -13,39 +12,44 @@ actual class PhoneAuthCredential(js: firebase.auth.AuthCredential) : AuthCredent actual class OAuthCredential(js: firebase.auth.AuthCredential) : AuthCredential(js) actual object EmailAuthProvider { - actual fun credentialWithEmail( + actual fun credential( email: String, password: String ): AuthCredential = AuthCredential(firebase.auth.EmailAuthProvider.credential(email, password)) } actual object FacebookAuthProvider { - actual fun credentialWithAccessToken(accessToken: String): AuthCredential = AuthCredential(firebase.auth.FacebookAuthProvider.credential(accessToken)) + actual fun credential(accessToken: String): AuthCredential = AuthCredential(firebase.auth.FacebookAuthProvider.credential(accessToken)) } actual object GithubAuthProvider { - actual fun credentialWithToken(token: String): AuthCredential = AuthCredential(firebase.auth.GithubAuthProvider.credential(token)) + actual fun credential(token: String): AuthCredential = AuthCredential(firebase.auth.GithubAuthProvider.credential(token)) } actual object GoogleAuthProvider { - actual fun credentialWithIDAndAccessToken(idToken: String, accessToken: String): AuthCredential = AuthCredential(firebase.auth.GoogleAuthProvider.credential(idToken, accessToken)) + actual fun credential(idToken: String, accessToken: String): AuthCredential = AuthCredential(firebase.auth.GoogleAuthProvider.credential(idToken, accessToken)) } actual class OAuthProvider(val js: firebase.auth.OAuthProvider, private val auth: FirebaseAuth) { actual constructor(provider: String, auth: FirebaseAuth) : this(firebase.auth.OAuthProvider(provider), auth) actual companion object { - actual fun credentialsWithAccessToken(providerId: String, accessToken: String): AuthCredential = getCredentials(providerId, accessToken = accessToken) - actual fun credentialsWithIDAndAccessToken(providerId: String, idToken: String, accessToken: String): AuthCredential = getCredentials(providerId, accessToken = accessToken, idToken = idToken) - actual fun credentialsWithIDRawNonceAndAccessToken(providerId: String, idToken: String, rawNonce: String, accessToken: String): AuthCredential = getCredentials(providerId, accessToken = accessToken, idToken = idToken, rawNonce = rawNonce) - actual fun credentialsWithIDAndRawNonce(providerId: String, idToken: String, rawNonce: String): AuthCredential = getCredentials(providerId, idToken = idToken, rawNonce = rawNonce) - private fun getCredentials(provider: String, accessToken: String? = null, idToken: String? = null, rawNonce: String? = null): AuthCredential = rethrow { + actual fun credentials(type: OAuthCredentialsType): AuthCredential { + return when (type) { + is OAuthCredentialsType.AccessToken -> getCredentials(type.providerId, accessToken = type.accessToken) + is OAuthCredentialsType.IdAndAccessToken -> getCredentials(type.providerId, idToken = type.idToken, accessToken = type.accessToken) + is OAuthCredentialsType.IdAndAccessTokenAndRawNonce -> getCredentials(type.providerId, idToken = type.idToken, rawNonce = type.rawNonce, accessToken = type.accessToken) + is OAuthCredentialsType.IdTokenAndRawNonce -> getCredentials(type.providerId, idToken = type.idToken, rawNonce = type.rawNonce) + } + } + + private fun getCredentials(providerId: String, accessToken: String? = null, idToken: String? = null, rawNonce: String? = null): AuthCredential = rethrow { val acT = accessToken val idT = idToken val rno = rawNonce - val provider = firebase.auth.OAuthProvider(provider) - val credentials = provider.credential(object : firebase.auth.OAuthCredentialOptions { + val provider = firebase.auth.OAuthProvider(providerId) + val credentials = provider.credential(object : firebase.auth.OAuthCredentialOptions { override val accessToken: String? = acT override val idToken: String? = idT override val rawNonce: String? = rno @@ -83,11 +87,11 @@ actual class PhoneAuthProvider(val js: firebase.auth.PhoneAuthProvider) { actual constructor(auth: FirebaseAuth) : this(firebase.auth.PhoneAuthProvider(auth.js)) - actual fun credentialWithVerificationIdAndSmsCode(verificationId: String, smsCode: String): PhoneAuthCredential = PhoneAuthCredential(firebase.auth.PhoneAuthProvider.credential(verificationId, smsCode)) + actual fun credential(verificationId: String, smsCode: String): PhoneAuthCredential = PhoneAuthCredential(firebase.auth.PhoneAuthProvider.credential(verificationId, smsCode)) actual suspend fun verifyPhoneNumber(phoneNumber: String, verificationProvider: PhoneVerificationProvider): AuthCredential = rethrow { val verificationId = js.verifyPhoneNumber(phoneNumber, verificationProvider.verifier).await() val verificationCode = verificationProvider.getVerificationCode(verificationId) - credentialWithVerificationIdAndSmsCode(verificationId, verificationCode) + credential(verificationId, verificationCode) } } @@ -97,5 +101,5 @@ actual interface PhoneVerificationProvider { } actual object TwitterAuthProvider { - actual fun credentialWithTokenAndSecret(token: String, secret: String): AuthCredential = AuthCredential(firebase.auth.TwitterAuthProvider.credential(token, secret)) + actual fun credential(token: String, secret: String): AuthCredential = AuthCredential(firebase.auth.TwitterAuthProvider.credential(token, secret)) } \ No newline at end of file diff --git a/firebase-auth/src/jsMain/kotlin/dev/gitlive/firebase/auth/multifactor.kt b/firebase-auth/src/jsMain/kotlin/dev/gitlive/firebase/auth/multifactor.kt index 1f0a4a534..41cd7edbf 100644 --- a/firebase-auth/src/jsMain/kotlin/dev/gitlive/firebase/auth/multifactor.kt +++ b/firebase-auth/src/jsMain/kotlin/dev/gitlive/firebase/auth/multifactor.kt @@ -20,8 +20,8 @@ actual class MultiFactor(val js: firebase.multifactor.MultiFactorUser) { actual class MultiFactorInfo(val js: firebase.multifactor.MultiFactorInfo) { actual val displayName: String? get() = rethrow { js.displayName } - actual val enrollmentTime: Long - get() = rethrow { (Date(js.enrollmentTime).getTime() / 1000.0).toLong() } + actual val enrollmentTime: Double + get() = rethrow { (Date(js.enrollmentTime).getTime() / 1000.0) } actual val factorId: String get() = rethrow { js.factorId } actual val uid: String diff --git a/firebase-auth/src/jsMain/kotlin/dev/gitlive/firebase/auth/user.kt b/firebase-auth/src/jsMain/kotlin/dev/gitlive/firebase/auth/user.kt index c55848fc5..580d15dd4 100644 --- a/firebase-auth/src/jsMain/kotlin/dev/gitlive/firebase/auth/user.kt +++ b/firebase-auth/src/jsMain/kotlin/dev/gitlive/firebase/auth/user.kt @@ -19,8 +19,8 @@ actual class FirebaseUser internal constructor(val js: firebase.user.User) { get() = rethrow { js.isAnonymous } actual val isEmailVerified: Boolean get() = rethrow { js.emailVerified } - actual val metaData: MetaData? - get() = rethrow { MetaData(js.metadata) } + actual val metaData: UserMetaData? + get() = rethrow { UserMetaData(js.metadata) } actual val multiFactor: MultiFactor get() = rethrow { MultiFactor(js.multiFactor) } actual val providerData: List @@ -42,9 +42,12 @@ actual class FirebaseUser internal constructor(val js: firebase.user.User) { actual suspend fun updateEmail(email: String) = rethrow { js.updateEmail(email).await() } actual suspend fun updatePassword(password: String) = rethrow { js.updatePassword(password).await() } actual suspend fun updatePhoneNumber(credential: PhoneAuthCredential) = rethrow { js.updatePhoneNumber(credential.js).await() } - actual suspend fun updateProfile(buildRequest: UserProfileChangeRequest.Builder.() -> Unit) = rethrow { - val request = UserProfileChangeRequest.Builder().apply(buildRequest).build() - js.updateProfile(request.js).await() + actual suspend fun updateProfile(displayName: String?, photoUrl: String?) = rethrow { + val request = object : firebase.user.ProfileUpdateRequest { + override val displayName: String? = displayName + override val photoURL: String? = photoUrl + } + js.updateProfile(request).await() } actual suspend fun verifyBeforeUpdateEmail(newEmail: String, actionCodeSettings: ActionCodeSettings?) = rethrow { js.verifyBeforeUpdateEmail(newEmail, actionCodeSettings?.js).await() } } @@ -64,33 +67,9 @@ actual class UserInfo(val js: firebase.user.UserInfo) { get() = rethrow { js.uid } } -actual class MetaData(val js: firebase.user.UserMetadata) { - actual val creationTime: Long? - get() = rethrow {js.creationTime?.let { (Date(it).getTime() / 1000.0).toLong() } } - actual val lastSignInTime: Long? - get() = rethrow {js.lastSignInTime?.let { (Date(it).getTime() / 1000.0).toLong() } } -} - -actual class UserProfileChangeRequest(val js: firebase.user.ProfileUpdateRequest) { - - actual class Builder { - - private var displayName: String? = null - private var photoURL: String? = null - - actual fun setDisplayName(displayName: String?): Builder = apply { - this.displayName = displayName - } - actual fun setPhotoURL(photoURL: String?): Builder = apply { - this.photoURL = photoURL - } - actual fun build(): UserProfileChangeRequest = UserProfileChangeRequest(object : firebase.user.ProfileUpdateRequest { - override val displayName: String? = this@Builder.displayName - override val photoURL: String? = this@Builder.photoURL - }) - } - actual val displayName: String? - get() = rethrow { js.displayName } - actual val photoURL: String? - get() = rethrow { js.photoURL } +actual class UserMetaData(val js: firebase.user.UserMetadata) { + actual val creationTime: Double? + get() = rethrow {js.creationTime?.let { (Date(it).getTime() / 1000.0) } } + actual val lastSignInTime: Double? + get() = rethrow {js.lastSignInTime?.let { (Date(it).getTime() / 1000.0) } } } From bcf4fe5479a89efed2f73d52ee8033b6968ec1a8 Mon Sep 17 00:00:00 2001 From: Gijs van Veen Date: Wed, 7 Oct 2020 22:03:39 +0200 Subject: [PATCH 19/32] Move ActionData into operator --- .../kotlin/dev/gitlive/firebase/auth/auth.kt | 20 +++++------ .../kotlin/dev/gitlive/firebase/auth/auth.kt | 35 +++++++++++++------ .../kotlin/dev/gitlive/firebase/auth/auth.kt | 20 +++++------ .../kotlin/dev/gitlive/firebase/auth/auth.kt | 20 +++++------ 4 files changed, 54 insertions(+), 41 deletions(-) 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 7a776d6b1..26e29f852 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 @@ -82,28 +82,28 @@ actual class AuthResult internal constructor(val android: com.google.firebase.au actual class ActionCodeResult(val android: com.google.firebase.auth.ActionCodeResult) { actual val operation: Operation get() = when (android.operation) { - com.google.firebase.auth.ActionCodeResult.PASSWORD_RESET -> Operation.PasswordReset - com.google.firebase.auth.ActionCodeResult.VERIFY_EMAIL -> Operation.VerifyEmail - com.google.firebase.auth.ActionCodeResult.RECOVER_EMAIL -> Operation.RecoverEmail + com.google.firebase.auth.ActionCodeResult.PASSWORD_RESET -> Operation.PasswordReset(this) + com.google.firebase.auth.ActionCodeResult.VERIFY_EMAIL -> Operation.VerifyEmail(this) + com.google.firebase.auth.ActionCodeResult.RECOVER_EMAIL -> Operation.RecoverEmail(this) com.google.firebase.auth.ActionCodeResult.ERROR -> Operation.Error com.google.firebase.auth.ActionCodeResult.SIGN_IN_WITH_EMAIL_LINK -> Operation.SignInWithEmailLink - com.google.firebase.auth.ActionCodeResult.VERIFY_BEFORE_CHANGE_EMAIL -> Operation.VerifyBeforeChangeEmail - com.google.firebase.auth.ActionCodeResult.REVERT_SECOND_FACTOR_ADDITION -> Operation.RevertSecondFactorAddition + com.google.firebase.auth.ActionCodeResult.VERIFY_BEFORE_CHANGE_EMAIL -> Operation.VerifyBeforeChangeEmail(this) + com.google.firebase.auth.ActionCodeResult.REVERT_SECOND_FACTOR_ADDITION -> Operation.RevertSecondFactorAddition(this) else -> Operation.Error } } -actual sealed class ActionCodeDataType { +internal actual sealed class ActionCodeDataType { - internal actual abstract fun dataForResult(result: ActionCodeResult): T? + actual abstract fun dataForResult(result: ActionCodeResult): T actual object Email : ActionCodeDataType() { - override fun dataForResult(result: ActionCodeResult): String? = result.android.info?.email + override fun dataForResult(result: ActionCodeResult): String = result.android.info!!.email } actual object PreviousEmail : ActionCodeDataType() { - override fun dataForResult(result: ActionCodeResult): String? = (result.android.info as? ActionCodeEmailInfo)?.previousEmail + override fun dataForResult(result: ActionCodeResult): String = (result.android.info as ActionCodeEmailInfo).previousEmail } - actual object MultiFactor : ActionCodeDataType() { + actual object MultiFactor : ActionCodeDataType() { override fun dataForResult(result: ActionCodeResult): MultiFactorInfo? = (result.android.info as? ActionCodeMultiFactorInfo)?.multiFactorInfo?.let { MultiFactorInfo(it) } } } 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 c8d04f224..ea28b1bd2 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 @@ -52,23 +52,36 @@ expect class SignInMethodQueryResult { val signInMethods: List } -enum class Operation { - PasswordReset, - VerifyEmail, - RecoverEmail, - Error, - SignInWithEmailLink, - VerifyBeforeChangeEmail, - RevertSecondFactorAddition +sealed class Operation { + class PasswordReset(result: ActionCodeResult) : Operation() { + val email: String = ActionCodeDataType.Email.dataForResult(result) + } + class VerifyEmail(result: ActionCodeResult) : Operation() { + val email: String = ActionCodeDataType.Email.dataForResult(result) + } + class RecoverEmail(result: ActionCodeResult) : Operation() { + val email: String = ActionCodeDataType.Email.dataForResult(result) + val previousEmail: String = ActionCodeDataType.PreviousEmail.dataForResult(result) + } + object Error : Operation() + object SignInWithEmailLink : Operation() + class VerifyBeforeChangeEmail(result: ActionCodeResult) : Operation() { + val email: String = ActionCodeDataType.Email.dataForResult(result) + val previousEmail: String = ActionCodeDataType.PreviousEmail.dataForResult(result) + } + class RevertSecondFactorAddition(result: ActionCodeResult) : Operation() { + val email: String = ActionCodeDataType.Email.dataForResult(result) + val multiFactorInfo: MultiFactorInfo? = ActionCodeDataType.MultiFactor.dataForResult(result) + } } -expect sealed class ActionCodeDataType { +internal expect sealed class ActionCodeDataType { - internal abstract fun dataForResult(result: ActionCodeResult): T? + abstract fun dataForResult(result: ActionCodeResult): T object Email : ActionCodeDataType object PreviousEmail : ActionCodeDataType - object MultiFactor : ActionCodeDataType + object MultiFactor : ActionCodeDataType } expect class ActionCodeSettings { 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 df515127b..c27dcdf7d 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 @@ -84,28 +84,28 @@ actual class AuthResult internal constructor(val ios: FIRAuthDataResult) { actual class ActionCodeResult(val ios: FIRActionCodeInfo) { actual val operation: Operation get() = when (ios.operation) { - FIRActionCodeOperationPasswordReset -> Operation.PasswordReset - FIRActionCodeOperationVerifyEmail -> Operation.VerifyEmail - FIRActionCodeOperationRecoverEmail -> Operation.RecoverEmail + FIRActionCodeOperationPasswordReset -> Operation.PasswordReset(this) + FIRActionCodeOperationVerifyEmail -> Operation.VerifyEmail(this) + FIRActionCodeOperationRecoverEmail -> Operation.RecoverEmail(this) FIRActionCodeOperationUnknown-> Operation.Error FIRActionCodeOperationEmailLink -> Operation.SignInWithEmailLink - FIRActionCodeOperationVerifyAndChangeEmail -> Operation.VerifyBeforeChangeEmail - FIRActionCodeOperationRevertSecondFactorAddition -> Operation.RevertSecondFactorAddition + FIRActionCodeOperationVerifyAndChangeEmail -> Operation.VerifyBeforeChangeEmail(this) + FIRActionCodeOperationRevertSecondFactorAddition -> Operation.RevertSecondFactorAddition(this) else -> Operation.Error } } -actual sealed class ActionCodeDataType { +internal actual sealed class ActionCodeDataType { - internal actual abstract fun dataForResult(result: ActionCodeResult): T? + actual abstract fun dataForResult(result: ActionCodeResult): T actual object Email : ActionCodeDataType() { - override fun dataForResult(result: ActionCodeResult): String? = result.ios.email + override fun dataForResult(result: ActionCodeResult): String = result.ios.email!! } actual object PreviousEmail : ActionCodeDataType() { - override fun dataForResult(result: ActionCodeResult): String? = result.ios.previousEmail + override fun dataForResult(result: ActionCodeResult): String = result.ios.previousEmail!! } - actual object MultiFactor : ActionCodeDataType() { + actual object MultiFactor : ActionCodeDataType() { override fun dataForResult(result: ActionCodeResult): MultiFactorInfo? = null } } 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 14b65046d..49e673d1b 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 @@ -86,27 +86,27 @@ actual class AuthResult internal constructor(val js: firebase.auth.AuthResult) { actual class ActionCodeResult(val js: firebase.auth.ActionCodeInfo) { actual val operation: Operation get() = when (js.operation) { - "PASSWORD_RESET" -> Operation.PasswordReset - "VERIFY_EMAIL" -> Operation.VerifyEmail - "RECOVER_EMAIL" -> Operation.RecoverEmail + "PASSWORD_RESET" -> Operation.PasswordReset(this) + "VERIFY_EMAIL" -> Operation.VerifyEmail(this) + "RECOVER_EMAIL" -> Operation.RecoverEmail(this) "EMAIL_SIGNIN" -> Operation.SignInWithEmailLink - "VERIFY_AND_CHANGE_EMAIL" -> Operation.VerifyBeforeChangeEmail - "REVERT_SECOND_FACTOR_ADDITION" -> Operation.RevertSecondFactorAddition + "VERIFY_AND_CHANGE_EMAIL" -> Operation.VerifyBeforeChangeEmail(this) + "REVERT_SECOND_FACTOR_ADDITION" -> Operation.RevertSecondFactorAddition(this) else -> Operation.Error } } -actual sealed class ActionCodeDataType { +internal actual sealed class ActionCodeDataType { - internal actual abstract fun dataForResult(result: ActionCodeResult): T? + actual abstract fun dataForResult(result: ActionCodeResult): T actual object Email : ActionCodeDataType() { - override fun dataForResult(result: ActionCodeResult): String? = result.js.data.email + override fun dataForResult(result: ActionCodeResult): String = result.js.data.email!! } actual object PreviousEmail : ActionCodeDataType() { - override fun dataForResult(result: ActionCodeResult): String? = result.js.data.previousEmail + override fun dataForResult(result: ActionCodeResult): String = result.js.data.previousEmail!! } - actual object MultiFactor : ActionCodeDataType() { + actual object MultiFactor : ActionCodeDataType() { override fun dataForResult(result: ActionCodeResult): MultiFactorInfo? = result.js.data.multiFactorInfo?.let { MultiFactorInfo(it) } } } From 8ba54ae738c814014ef8edd2bd9812f83a290fb2 Mon Sep 17 00:00:00 2001 From: Gijs van Veen Date: Wed, 7 Oct 2020 22:08:14 +0200 Subject: [PATCH 20/32] fix test --- .../src/commonTest/kotlin/dev/gitlive/firebase/auth/auth.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 c01a21dda..dac2dcbde 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 @@ -85,7 +85,7 @@ class FirebaseAuthTest { @Test fun testSignInWithCredential() = runTest { - val credential = EmailAuthProvider.credentialWithEmail("test@test.com", "test123") + val credential = EmailAuthProvider.credential("test@test.com", "test123") val result = Firebase.auth.signInWithCredential(credential) assertEquals("mn8kgIFnxLO7il8GpTa5g0ObP6I2", result.user!!.uid) From 5a215b3706b0dfcdfc7c84d44e149d1cfed56cc3 Mon Sep 17 00:00:00 2001 From: nbransby Date: Tue, 20 Oct 2020 09:54:38 +0100 Subject: [PATCH 21/32] Revert passing a Sealed class to credentials. This is a partial revert of commit dcbe856c --- .../dev/gitlive/firebase/auth/credentials.kt | 48 ++++++++++--------- .../dev/gitlive/firebase/auth/credentials.kt | 28 ++++------- .../dev/gitlive/firebase/auth/credentials.kt | 26 +++++----- .../dev/gitlive/firebase/auth/credentials.kt | 33 ++++++------- 4 files changed, 60 insertions(+), 75 deletions(-) diff --git a/firebase-auth/src/androidMain/kotlin/dev/gitlive/firebase/auth/credentials.kt b/firebase-auth/src/androidMain/kotlin/dev/gitlive/firebase/auth/credentials.kt index c1e1340d1..7da683b4c 100644 --- a/firebase-auth/src/androidMain/kotlin/dev/gitlive/firebase/auth/credentials.kt +++ b/firebase-auth/src/androidMain/kotlin/dev/gitlive/firebase/auth/credentials.kt @@ -23,44 +23,46 @@ actual class PhoneAuthCredential(override val android: com.google.firebase.auth. actual class OAuthCredential(override val android: com.google.firebase.auth.OAuthCredential) : AuthCredential(android) actual object EmailAuthProvider { - actual fun credential( + actual fun credentialWithEmail( email: String, password: String ): AuthCredential = AuthCredential(com.google.firebase.auth.EmailAuthProvider.getCredential(email, password)) } actual object FacebookAuthProvider { - actual fun credential(accessToken: String): AuthCredential = AuthCredential(com.google.firebase.auth.FacebookAuthProvider.getCredential(accessToken)) + actual fun credentialWithAccessToken(accessToken: String): AuthCredential = AuthCredential(com.google.firebase.auth.FacebookAuthProvider.getCredential(accessToken)) } actual object GithubAuthProvider { - actual fun credential(token: String): AuthCredential = AuthCredential(com.google.firebase.auth.GithubAuthProvider.getCredential(token)) + actual fun credentialWithToken(token: String): AuthCredential = AuthCredential(com.google.firebase.auth.GithubAuthProvider.getCredential(token)) } actual object GoogleAuthProvider { - actual fun credential(idToken: String, accessToken: String): AuthCredential = AuthCredential(com.google.firebase.auth.GoogleAuthProvider.getCredential(idToken, accessToken)) + actual fun credentialWithIDAndAccessToken(idToken: String, accessToken: String): AuthCredential = AuthCredential(com.google.firebase.auth.GoogleAuthProvider.getCredential(idToken, accessToken)) } actual class OAuthProvider(val android: com.google.firebase.auth.OAuthProvider.Builder, private val auth: FirebaseAuth) { actual constructor(provider: String, auth: FirebaseAuth) : this(com.google.firebase.auth.OAuthProvider.newBuilder(provider, auth.android), auth) actual companion object { - actual fun credentials(type: OAuthCredentialsType): AuthCredential { - val credential = com.google.firebase.auth.OAuthProvider.newCredentialBuilder(type.providerId).apply { - when (type) { - is OAuthCredentialsType.AccessToken -> accessToken = type.accessToken - is OAuthCredentialsType.IdAndAccessToken -> { - accessToken = type.accessToken - setIdToken(type.idToken) - } - is OAuthCredentialsType.IdAndAccessTokenAndRawNonce -> { - accessToken = type.accessToken - setIdTokenWithRawNonce(type.idToken, type.rawNonce) - } - is OAuthCredentialsType.IdTokenAndRawNonce -> { - setIdTokenWithRawNonce(type.idToken, type.rawNonce) - } - } + actual fun credentialsWithAccessToken(providerId: String, accessToken: String): AuthCredential = createCredentials(providerId) { + this.accessToken = accessToken + } + actual fun credentialsWithIDAndAccessToken(providerId: String, idToken: String, accessToken: String): AuthCredential = createCredentials(providerId) { + setIdToken(idToken) + this.accessToken = accessToken + } + actual fun credentialsWithIDRawNonceAndAccessToken(providerId: String, idToken: String, rawNonce: String, accessToken: String): AuthCredential = createCredentials(providerId) { + setIdTokenWithRawNonce(idToken, rawNonce) + this.accessToken = accessToken + } + actual fun credentialsWithIDAndRawNonce(providerId: String, idToken: String, rawNonce: String): AuthCredential = createCredentials(providerId) { + setIdTokenWithRawNonce(idToken, rawNonce) + } + + private fun createCredentials(providerId: String, block: com.google.firebase.auth.OAuthProvider.CredentialBuilder.() -> Unit): AuthCredential { + val credential = com.google.firebase.auth.OAuthProvider.newCredentialBuilder(providerId).apply { + block() }.build() return (credential as? com.google.firebase.auth.OAuthCredential)?.let { OAuthCredential(it) } ?: AuthCredential(credential) } @@ -85,7 +87,7 @@ actual class PhoneAuthProvider(val android: com.google.firebase.auth.PhoneAuthPr actual constructor(auth: FirebaseAuth) : this(com.google.firebase.auth.PhoneAuthProvider.getInstance(auth.android)) - actual fun credential(verificationId: String, smsCode: String): PhoneAuthCredential = PhoneAuthCredential(com.google.firebase.auth.PhoneAuthProvider.getCredential(verificationId, smsCode)) + actual fun credentialWithVerificationIdAndSmsCode(verificationId: String, smsCode: String): PhoneAuthCredential = PhoneAuthCredential(com.google.firebase.auth.PhoneAuthProvider.getCredential(verificationId, smsCode)) actual suspend fun verifyPhoneNumber(phoneNumber: String, verificationProvider: PhoneVerificationProvider): AuthCredential = coroutineScope { val response = CompletableDeferred>() val callback = object : @@ -100,7 +102,7 @@ actual class PhoneAuthProvider(val android: com.google.firebase.auth.PhoneAuthPr val code = verificationProvider.getVerificationCode() try { val credentials = - credential(verificationId, code) + credentialWithVerificationIdAndSmsCode(verificationId, code) response.complete(Result.success(credentials)) } catch (e: Exception) { response.complete(Result.failure(e)) @@ -132,5 +134,5 @@ actual interface PhoneVerificationProvider { } actual object TwitterAuthProvider { - actual fun credential(token: String, secret: String): AuthCredential = AuthCredential(com.google.firebase.auth.TwitterAuthProvider.getCredential(token, secret)) + actual fun credentialWithTokenAndSecret(token: String, secret: String): AuthCredential = AuthCredential(com.google.firebase.auth.TwitterAuthProvider.getCredential(token, secret)) } diff --git a/firebase-auth/src/commonMain/kotlin/dev/gitlive/firebase/auth/credentials.kt b/firebase-auth/src/commonMain/kotlin/dev/gitlive/firebase/auth/credentials.kt index 6146f5348..c0d88a703 100644 --- a/firebase-auth/src/commonMain/kotlin/dev/gitlive/firebase/auth/credentials.kt +++ b/firebase-auth/src/commonMain/kotlin/dev/gitlive/firebase/auth/credentials.kt @@ -5,8 +5,6 @@ package dev.gitlive.firebase.auth import dev.gitlive.firebase.Firebase -import kotlin.jvm.JvmName -import kotlin.js.JsName expect open class AuthCredential { val providerId: String @@ -16,33 +14,27 @@ expect class PhoneAuthCredential : AuthCredential expect class OAuthCredential : AuthCredential expect object EmailAuthProvider { - fun credential(email: String, password: String): AuthCredential + fun credentialWithEmail(email: String, password: String): AuthCredential } expect object FacebookAuthProvider { - fun credential(accessToken: String): AuthCredential + fun credentialWithAccessToken(accessToken: String): AuthCredential } expect object GithubAuthProvider { - fun credential(token: String): AuthCredential + fun credentialWithToken(token: String): AuthCredential } expect object GoogleAuthProvider { - fun credential(idToken: String, accessToken: String): AuthCredential -} - -sealed class OAuthCredentialsType { - abstract val providerId: String - data class AccessToken(val accessToken: String, override val providerId: String) : OAuthCredentialsType() - data class IdAndAccessToken(val idToken: String, val accessToken: String, override val providerId: String) : OAuthCredentialsType() - data class IdAndAccessTokenAndRawNonce(val idToken: String, val accessToken: String, val rawNonce: String, override val providerId: String) : OAuthCredentialsType() - data class IdTokenAndRawNonce(val idToken: String, val rawNonce: String, override val providerId: String) : OAuthCredentialsType() - + fun credentialWithIDAndAccessToken(idToken: String, accessToken: String): AuthCredential } expect class OAuthProvider constructor(provider: String, auth: FirebaseAuth = Firebase.auth) { companion object { - fun credentials(type: OAuthCredentialsType): AuthCredential + fun credentialsWithAccessToken(providerId: String, accessToken: String): AuthCredential + fun credentialsWithIDAndAccessToken(providerId: String, idToken: String, accessToken: String): AuthCredential + fun credentialsWithIDRawNonceAndAccessToken(providerId: String, idToken: String, rawNonce: String, accessToken: String): AuthCredential + fun credentialsWithIDAndRawNonce(providerId: String, idToken: String, rawNonce: String): AuthCredential } fun addScope(vararg scope: String) @@ -54,7 +46,7 @@ expect class OAuthProvider constructor(provider: String, auth: FirebaseAuth = Fi expect class SignInProvider expect class PhoneAuthProvider constructor(auth: FirebaseAuth = Firebase.auth) { - fun credential(verificationId: String, smsCode: String): PhoneAuthCredential + fun credentialWithVerificationIdAndSmsCode(verificationId: String, smsCode: String): PhoneAuthCredential suspend fun verifyPhoneNumber(phoneNumber: String, verificationProvider: PhoneVerificationProvider): AuthCredential } @@ -62,5 +54,5 @@ expect class PhoneAuthProvider constructor(auth: FirebaseAuth = Firebase.auth) { expect interface PhoneVerificationProvider expect object TwitterAuthProvider { - fun credential(token: String, secret: String): AuthCredential + fun credentialWithTokenAndSecret(token: String, secret: String): AuthCredential } diff --git a/firebase-auth/src/iosMain/kotlin/dev/gitlive/firebase/auth/credentials.kt b/firebase-auth/src/iosMain/kotlin/dev/gitlive/firebase/auth/credentials.kt index 88b8312cf..8be084064 100644 --- a/firebase-auth/src/iosMain/kotlin/dev/gitlive/firebase/auth/credentials.kt +++ b/firebase-auth/src/iosMain/kotlin/dev/gitlive/firebase/auth/credentials.kt @@ -15,7 +15,7 @@ actual class PhoneAuthCredential(override val ios: FIRPhoneAuthCredential) : Aut actual class OAuthCredential(override val ios: FIROAuthCredential) : AuthCredential(ios) actual object EmailAuthProvider { - actual fun credential( + actual fun credentialWithEmail( email: String, password: String ): AuthCredential = @@ -23,29 +23,25 @@ actual object EmailAuthProvider { } actual object FacebookAuthProvider { - actual fun credential(accessToken: String): AuthCredential = AuthCredential(FIRFacebookAuthProvider.credentialWithAccessToken(accessToken)) + actual fun credentialWithAccessToken(accessToken: String): AuthCredential = AuthCredential(FIRFacebookAuthProvider.credentialWithAccessToken(accessToken)) } actual object GithubAuthProvider { - actual fun credential(token: String): AuthCredential = AuthCredential(FIRGitHubAuthProvider.credentialWithToken(token)) + actual fun credentialWithToken(token: String): AuthCredential = AuthCredential(FIRGitHubAuthProvider.credentialWithToken(token)) } actual object GoogleAuthProvider { - actual fun credential(idToken: String, accessToken: String): AuthCredential = AuthCredential(FIRGoogleAuthProvider.credentialWithIDToken(idToken, accessToken)) + actual fun credentialWithIDAndAccessToken(idToken: String, accessToken: String): AuthCredential = AuthCredential(FIRGoogleAuthProvider.credentialWithIDToken(idToken, accessToken)) } actual class OAuthProvider(val ios: FIROAuthProvider, private val auth: FirebaseAuth) { actual constructor(provider: String, auth: FirebaseAuth) : this(FIROAuthProvider.providerWithProviderID(provider, auth.ios), auth) actual companion object { - actual fun credentials(type: OAuthCredentialsType): AuthCredential { - return AuthCredential(when (type) { - is OAuthCredentialsType.AccessToken -> FIROAuthProvider.credentialWithProviderID(type.providerId, type.accessToken) - is OAuthCredentialsType.IdAndAccessToken -> FIROAuthProvider.credentialWithProviderID(providerID = type.providerId, IDToken = type.idToken, accessToken = type.accessToken) - is OAuthCredentialsType.IdAndAccessTokenAndRawNonce -> FIROAuthProvider.credentialWithProviderID(providerID = type.providerId, IDToken = type.idToken, rawNonce = type.rawNonce, accessToken = type.accessToken) - is OAuthCredentialsType.IdTokenAndRawNonce -> FIROAuthProvider.credentialWithProviderID(providerID = type.providerId, IDToken = type.idToken, rawNonce = type.rawNonce) - }) - } + actual fun credentialsWithAccessToken(providerId: String, accessToken: String): AuthCredential = AuthCredential(FIROAuthProvider.credentialWithProviderID(providerId, accessToken)) + actual fun credentialsWithIDAndAccessToken(providerId: String, idToken: String, accessToken: String): AuthCredential = AuthCredential(FIROAuthProvider.credentialWithProviderID(providerID = providerId, IDToken = idToken, accessToken = accessToken)) + actual fun credentialsWithIDRawNonceAndAccessToken(providerId: String, idToken: String, rawNonce: String, accessToken: String): AuthCredential = AuthCredential(FIROAuthProvider.credentialWithProviderID(providerID = providerId, IDToken = idToken, rawNonce = rawNonce, accessToken = accessToken)) + actual fun credentialsWithIDAndRawNonce(providerId: String, idToken: String, rawNonce: String): AuthCredential = AuthCredential(FIROAuthProvider.credentialWithProviderID(providerID = providerId, IDToken = idToken, rawNonce = rawNonce)) } actual fun addScope(vararg scope: String) { @@ -76,11 +72,11 @@ actual class PhoneAuthProvider(val ios: FIRPhoneAuthProvider) { actual constructor(auth: FirebaseAuth) : this(FIRPhoneAuthProvider.providerWithAuth(auth.ios)) - actual fun credential(verificationId: String, smsCode: String): PhoneAuthCredential = PhoneAuthCredential(ios.credentialWithVerificationID(verificationId, smsCode)) + actual fun credentialWithVerificationIdAndSmsCode(verificationId: String, smsCode: String): PhoneAuthCredential = PhoneAuthCredential(ios.credentialWithVerificationID(verificationId, smsCode)) actual suspend fun verifyPhoneNumber(phoneNumber: String, verificationProvider: PhoneVerificationProvider): AuthCredential { val verificationId: String = ios.awaitExpectedResult { ios.verifyPhoneNumber(phoneNumber, verificationProvider.delegate, it) } val verificationCode = verificationProvider.getVerificationCode() - return credential(verificationId, verificationCode) + return credentialWithVerificationIdAndSmsCode(verificationId, verificationCode) } } @@ -90,5 +86,5 @@ actual interface PhoneVerificationProvider { } actual object TwitterAuthProvider { - actual fun credential(token: String, secret: String): AuthCredential = AuthCredential(FIRTwitterAuthProvider.credentialWithToken(token, secret)) + actual fun credentialWithTokenAndSecret(token: String, secret: String): AuthCredential = AuthCredential(FIRTwitterAuthProvider.credentialWithToken(token, secret)) } \ No newline at end of file diff --git a/firebase-auth/src/jsMain/kotlin/dev/gitlive/firebase/auth/credentials.kt b/firebase-auth/src/jsMain/kotlin/dev/gitlive/firebase/auth/credentials.kt index 09ce0c990..31bccfb4a 100644 --- a/firebase-auth/src/jsMain/kotlin/dev/gitlive/firebase/auth/credentials.kt +++ b/firebase-auth/src/jsMain/kotlin/dev/gitlive/firebase/auth/credentials.kt @@ -12,44 +12,39 @@ actual class PhoneAuthCredential(js: firebase.auth.AuthCredential) : AuthCredent actual class OAuthCredential(js: firebase.auth.AuthCredential) : AuthCredential(js) actual object EmailAuthProvider { - actual fun credential( + actual fun credentialWithEmail( email: String, password: String ): AuthCredential = AuthCredential(firebase.auth.EmailAuthProvider.credential(email, password)) } actual object FacebookAuthProvider { - actual fun credential(accessToken: String): AuthCredential = AuthCredential(firebase.auth.FacebookAuthProvider.credential(accessToken)) + actual fun credentialWithAccessToken(accessToken: String): AuthCredential = AuthCredential(firebase.auth.FacebookAuthProvider.credential(accessToken)) } actual object GithubAuthProvider { - actual fun credential(token: String): AuthCredential = AuthCredential(firebase.auth.GithubAuthProvider.credential(token)) + actual fun credentialWithToken(token: String): AuthCredential = AuthCredential(firebase.auth.GithubAuthProvider.credential(token)) } actual object GoogleAuthProvider { - actual fun credential(idToken: String, accessToken: String): AuthCredential = AuthCredential(firebase.auth.GoogleAuthProvider.credential(idToken, accessToken)) + actual fun credentialWithIDAndAccessToken(idToken: String, accessToken: String): AuthCredential = AuthCredential(firebase.auth.GoogleAuthProvider.credential(idToken, accessToken)) } actual class OAuthProvider(val js: firebase.auth.OAuthProvider, private val auth: FirebaseAuth) { actual constructor(provider: String, auth: FirebaseAuth) : this(firebase.auth.OAuthProvider(provider), auth) actual companion object { + actual fun credentialsWithAccessToken(providerId: String, accessToken: String): AuthCredential = getCredentials(providerId, accessToken = accessToken) + actual fun credentialsWithIDAndAccessToken(providerId: String, idToken: String, accessToken: String): AuthCredential = getCredentials(providerId, accessToken = accessToken, idToken = idToken) + actual fun credentialsWithIDRawNonceAndAccessToken(providerId: String, idToken: String, rawNonce: String, accessToken: String): AuthCredential = getCredentials(providerId, accessToken = accessToken, idToken = idToken, rawNonce = rawNonce) + actual fun credentialsWithIDAndRawNonce(providerId: String, idToken: String, rawNonce: String): AuthCredential = getCredentials(providerId, idToken = idToken, rawNonce = rawNonce) - actual fun credentials(type: OAuthCredentialsType): AuthCredential { - return when (type) { - is OAuthCredentialsType.AccessToken -> getCredentials(type.providerId, accessToken = type.accessToken) - is OAuthCredentialsType.IdAndAccessToken -> getCredentials(type.providerId, idToken = type.idToken, accessToken = type.accessToken) - is OAuthCredentialsType.IdAndAccessTokenAndRawNonce -> getCredentials(type.providerId, idToken = type.idToken, rawNonce = type.rawNonce, accessToken = type.accessToken) - is OAuthCredentialsType.IdTokenAndRawNonce -> getCredentials(type.providerId, idToken = type.idToken, rawNonce = type.rawNonce) - } - } - - private fun getCredentials(providerId: String, accessToken: String? = null, idToken: String? = null, rawNonce: String? = null): AuthCredential = rethrow { + private fun getCredentials(provider: String, accessToken: String? = null, idToken: String? = null, rawNonce: String? = null): AuthCredential = rethrow { val acT = accessToken val idT = idToken val rno = rawNonce - val provider = firebase.auth.OAuthProvider(providerId) - val credentials = provider.credential(object : firebase.auth.OAuthCredentialOptions { + val provider = firebase.auth.OAuthProvider(provider) + val credentials = provider.credential(object : firebase.auth.OAuthCredentialOptions { override val accessToken: String? = acT override val idToken: String? = idT override val rawNonce: String? = rno @@ -87,11 +82,11 @@ actual class PhoneAuthProvider(val js: firebase.auth.PhoneAuthProvider) { actual constructor(auth: FirebaseAuth) : this(firebase.auth.PhoneAuthProvider(auth.js)) - actual fun credential(verificationId: String, smsCode: String): PhoneAuthCredential = PhoneAuthCredential(firebase.auth.PhoneAuthProvider.credential(verificationId, smsCode)) + actual fun credentialWithVerificationIdAndSmsCode(verificationId: String, smsCode: String): PhoneAuthCredential = PhoneAuthCredential(firebase.auth.PhoneAuthProvider.credential(verificationId, smsCode)) actual suspend fun verifyPhoneNumber(phoneNumber: String, verificationProvider: PhoneVerificationProvider): AuthCredential = rethrow { val verificationId = js.verifyPhoneNumber(phoneNumber, verificationProvider.verifier).await() val verificationCode = verificationProvider.getVerificationCode(verificationId) - credential(verificationId, verificationCode) + credentialWithVerificationIdAndSmsCode(verificationId, verificationCode) } } @@ -101,5 +96,5 @@ actual interface PhoneVerificationProvider { } actual object TwitterAuthProvider { - actual fun credential(token: String, secret: String): AuthCredential = AuthCredential(firebase.auth.TwitterAuthProvider.credential(token, secret)) + actual fun credentialWithTokenAndSecret(token: String, secret: String): AuthCredential = AuthCredential(firebase.auth.TwitterAuthProvider.credential(token, secret)) } \ No newline at end of file From 826f1b3bcfbcd351fdb278b2dc1f38bd5b808376 Mon Sep 17 00:00:00 2001 From: nbransby Date: Tue, 20 Oct 2020 11:01:41 +0100 Subject: [PATCH 22/32] make ActionCodeSettings a data class --- .../kotlin/dev/gitlive/firebase/auth/auth.kt | 39 ++++----------- .../kotlin/dev/gitlive/firebase/auth/auth.kt | 25 ++++------ .../kotlin/dev/gitlive/firebase/auth/auth.kt | 37 ++++----------- .../kotlin/dev/gitlive/firebase/auth/auth.kt | 47 ++++--------------- 4 files changed, 35 insertions(+), 113 deletions(-) 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 26e29f852..3c5658f0c 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 @@ -52,10 +52,10 @@ actual class FirebaseAuth internal constructor(val android: com.google.firebase. actual suspend fun fetchSignInMethodsForEmail(email: String): SignInMethodQueryResult = SignInMethodQueryResult(android.fetchSignInMethodsForEmail(email).await()) actual suspend fun sendPasswordResetEmail(email: String, actionCodeSettings: ActionCodeSettings?) { - android.sendPasswordResetEmail(email, actionCodeSettings?.android).await() + android.sendPasswordResetEmail(email, actionCodeSettings?.toAndroid()).await() } - actual suspend fun sendSignInLinkToEmail(email: String, actionCodeSettings: ActionCodeSettings) = android.sendSignInLinkToEmail(email, actionCodeSettings.android).await().run { Unit } + actual suspend fun sendSignInLinkToEmail(email: String, actionCodeSettings: ActionCodeSettings) = android.sendSignInLinkToEmail(email, actionCodeSettings.toAndroid()).await().run { Unit } actual suspend fun signInWithEmailAndPassword(email: String, password: String) = AuthResult(android.signInWithEmailAndPassword(email, password).await()) @@ -113,34 +113,13 @@ actual class SignInMethodQueryResult(val android: com.google.firebase.auth.SignI get() = android.signInMethods ?: emptyList() } -actual class ActionCodeSettings private constructor(val android: com.google.firebase.auth.ActionCodeSettings) { - - actual constructor(url: String, - androidPackageName: AndroidPackageName?, - dynamicLinkDomain: String?, - canHandleCodeInApp: Boolean, - iOSBundleId: String? - ) : this(com.google.firebase.auth.ActionCodeSettings.newBuilder().apply { - this.url = url - androidPackageName?.let { - this.setAndroidPackageName(it.androidPackageName, it.installIfNotAvailable, it.minimumVersion) - } - this.dynamicLinkDomain = dynamicLinkDomain - this.handleCodeInApp = canHandleCodeInApp - this.iosBundleId = iosBundleId - }.build()) - - actual val canHandleCodeInApp: Boolean - get() = android.canHandleCodeInApp() - actual val androidPackageName: AndroidPackageName? - get() = android.androidPackageName?.let { - AndroidPackageName(it, android.androidInstallApp, android.androidMinimumVersion) - } - actual val iOSBundle: String? - get() = android.iosBundle - actual val url: String - get() = android.url -} +private fun ActionCodeSettings.toAndroid() = com.google.firebase.auth.ActionCodeSettings.newBuilder() + .setUrl(url) + .also { androidPackageName?.run { it.setAndroidPackageName(packageName, installIfNotAvailable, minimumVersion) } } + .also { dynamicLinkDomain?.run { it.setDynamicLinkDomain(this) } } + .setHandleCodeInApp(canHandleCodeInApp) + .also { iOSBundleId?.run { it.setIOSBundleId(this) } } + .build() actual typealias FirebaseAuthException = com.google.firebase.auth.FirebaseAuthException actual typealias FirebaseAuthActionCodeException = com.google.firebase.auth.FirebaseAuthActionCodeException 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 ea28b1bd2..86c04e38a 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 @@ -84,22 +84,15 @@ internal expect sealed class ActionCodeDataType { object MultiFactor : ActionCodeDataType } -expect class ActionCodeSettings { - constructor( - url: String, - androidPackageName: AndroidPackageName? = null, - dynamicLinkDomain: String? = null, - canHandleCodeInApp: Boolean = false, - iOSBundleId: String? = null - ) - - val canHandleCodeInApp: Boolean - val androidPackageName: AndroidPackageName? - val iOSBundle: String? - val url: String -} - -data class AndroidPackageName(val androidPackageName: String, val installIfNotAvailable: Boolean, val minimumVersion: String?) +data class ActionCodeSettings( + val url: String, + val androidPackageName: AndroidPackageName? = null, + val dynamicLinkDomain: String? = null, + val canHandleCodeInApp: Boolean = false, + val iOSBundleId: String? = null +) + +data class AndroidPackageName(val packageName: String, val installIfNotAvailable: Boolean, val minimumVersion: String?) expect open class FirebaseAuthException : FirebaseException expect class FirebaseAuthActionCodeException : FirebaseAuthException 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 c27dcdf7d..558bba8de 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 @@ -53,10 +53,10 @@ actual class FirebaseAuth internal constructor(val ios: FIRAuth) { } actual suspend fun sendPasswordResetEmail(email: String, actionCodeSettings: ActionCodeSettings?) { - ios.await { actionCodeSettings?.let { actionSettings -> sendPasswordResetWithEmail(email, actionSettings.ios, it) } ?: sendPasswordResetWithEmail(email = email, completion = it) } + ios.await { actionCodeSettings?.let { actionSettings -> sendPasswordResetWithEmail(email, actionSettings.toIos(), it) } ?: sendPasswordResetWithEmail(email = email, completion = it) } } - actual suspend fun sendSignInLinkToEmail(email: String, actionCodeSettings: ActionCodeSettings) = ios.await { sendSignInLinkToEmail(email, actionCodeSettings.ios, it) }.run { Unit } + actual suspend fun sendSignInLinkToEmail(email: String, actionCodeSettings: ActionCodeSettings) = ios.await { sendSignInLinkToEmail(email, actionCodeSettings.toIos(), it) }.run { Unit } actual suspend fun signInWithEmailAndPassword(email: String, password: String) = AuthResult(ios.awaitExpectedResult { signInWithEmail(email = email, password = password, completion = it) }) @@ -112,33 +112,12 @@ internal actual sealed class ActionCodeDataType { actual class SignInMethodQueryResult(actual val signInMethods: List) -actual class ActionCodeSettings private constructor(val ios: FIRActionCodeSettings) { - - actual constructor(url: String, - androidPackageName: AndroidPackageName?, - dynamicLinkDomain: String?, - canHandleCodeInApp: Boolean, - iOSBundleId: String? - ) : this(FIRActionCodeSettings().apply { - this.URL = NSURL.URLWithString(url) - androidPackageName?.let { - this.setAndroidPackageName(it.androidPackageName, it.installIfNotAvailable, it.minimumVersion) - } - this.dynamicLinkDomain = dynamicLinkDomain - this.handleCodeInApp = canHandleCodeInApp - iOSBundleId?.let { setIOSBundleID(it) } - }) - - actual val canHandleCodeInApp: Boolean - get() = ios.handleCodeInApp() - actual val androidPackageName: AndroidPackageName? - get() = ios.androidPackageName?.let { - AndroidPackageName(it, ios.androidInstallIfNotAvailable, ios.androidMinimumVersion) - } - actual val iOSBundle: String? - get() = ios.iOSBundleID - actual val url: String - get() = ios.URL?.absoluteString ?: "" +private fun ActionCodeSettings.toIos() = FIRActionCodeSettings().let { + it.URL = NSURL.URLWithString(url) + androidPackageName?.run { it.setAndroidPackageName(androidPackageName, installIfNotAvailable, minimumVersion) } + it.dynamicLinkDomain = dynamicLinkDomain + it.handleCodeInApp = canHandleCodeInApp + iOSBundleId?.run { it.setIOSBundleID(this) } } actual open class FirebaseAuthException(message: String): FirebaseException(message) 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 49e673d1b..092c8c712 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 @@ -4,10 +4,9 @@ package dev.gitlive.firebase.auth -import dev.gitlive.firebase.* -import kotlinx.coroutines.await import kotlinx.coroutines.channels.awaitClose import kotlinx.coroutines.flow.callbackFlow +import kotlin.js.json actual val Firebase.auth get() = rethrow { dev.gitlive.firebase.auth; FirebaseAuth(firebase.auth()) } @@ -48,10 +47,10 @@ actual class FirebaseAuth internal constructor(val js: firebase.auth.Auth) { actual suspend fun fetchSignInMethodsForEmail(email: String): SignInMethodQueryResult = rethrow { SignInMethodQueryResult(js.fetchSignInMethodsForEmail(email).await().asList()) } actual suspend fun sendPasswordResetEmail(email: String, actionCodeSettings: ActionCodeSettings?) = - rethrow { js.sendPasswordResetEmail(email, actionCodeSettings?.js).await() } + rethrow { js.sendPasswordResetEmail(email, actionCodeSettings?.toJson()).await() } actual suspend fun sendSignInLinkToEmail(email: String, actionCodeSettings: ActionCodeSettings) = - rethrow { js.sendSignInLinkToEmail(email, actionCodeSettings.js).await() } + rethrow { js.sendSignInLinkToEmail(email, actionCodeSettings.toJson()).await() } actual suspend fun signInWithEmailAndPassword(email: String, password: String) = rethrow { AuthResult(js.signInWithEmailAndPassword(email, password).await()) } @@ -113,40 +112,12 @@ internal actual sealed class ActionCodeDataType { actual class SignInMethodQueryResult(actual val signInMethods: List) -actual class ActionCodeSettings private constructor(val js: firebase.auth.ActionCodeSettings) { - - actual constructor(url: String, - androidPackageName: AndroidPackageName?, - dynamicLinkDomain: String?, - canHandleCodeInApp: Boolean, - iOSBundleId: String? - ) : this(object : firebase.auth.ActionCodeSettings { - override val android: firebase.auth.AndroidActionCodeSettings? = androidPackageName?.let { androidPackageName -> object : firebase.auth.AndroidActionCodeSettings { - override val installApp: Boolean get() = androidPackageName.installIfNotAvailable - override val minimumVersion: String? get() = androidPackageName.minimumVersion - override val packageName: String get() = androidPackageName.androidPackageName - - } } - override val dynamicLinkDomain: String? = dynamicLinkDomain - override val handleCodeInApp: Boolean? = canHandleCodeInApp - override val iOS: firebase.auth.iOSActionCodeSettings? = iOSBundleId?.let { iOSBundleId -> - object : firebase.auth.iOSActionCodeSettings { - override val bundleId: String? - get() = iOSBundleId - } - } - override val url: String = url - }) - - actual val canHandleCodeInApp: Boolean - get() = js.handleCodeInApp ?: false - actual val androidPackageName: AndroidPackageName? - get() = js.android?.let { AndroidPackageName(it.packageName, it.installApp ?: false, it.minimumVersion) } - actual val iOSBundle: String? - get() = js.iOS?.bundleId - actual val url: String - get() = js.url -} +private fun ActionCodeSettings.toJson() = json( + "android" to (androidPackageName?.run { json("installApp" to installIfNotAvailable, "minimumVersion" to minimumVersion, "packageName" to packageName) } ?: undefined), + "dynamicLinkDomain" to (dynamicLinkDomain ?: undefined), + "handleCodeInApp" to canHandleCodeInApp, + "ios" to (iOSBundleId?.run { json("bundleId" to iOSBundleId) } ?: undefined) +) actual open class FirebaseAuthException(code: String?, cause: Throwable): FirebaseException(code, cause) actual open class FirebaseAuthActionCodeException(code: String?, cause: Throwable): FirebaseAuthException(code, cause) From 151571d044cd53ce20ccc71af46568b04df6972c Mon Sep 17 00:00:00 2001 From: nbransby Date: Tue, 20 Oct 2020 14:09:49 +0100 Subject: [PATCH 23/32] Revert "fix test" This reverts commit 8ba54ae7 --- .../src/commonTest/kotlin/dev/gitlive/firebase/auth/auth.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 dac2dcbde..c01a21dda 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 @@ -85,7 +85,7 @@ class FirebaseAuthTest { @Test fun testSignInWithCredential() = runTest { - val credential = EmailAuthProvider.credential("test@test.com", "test123") + val credential = EmailAuthProvider.credentialWithEmail("test@test.com", "test123") val result = Firebase.auth.signInWithCredential(credential) assertEquals("mn8kgIFnxLO7il8GpTa5g0ObP6I2", result.user!!.uid) From 295b2a75d4e304a9930cd65fdf92fd28c0004127 Mon Sep 17 00:00:00 2001 From: nbransby Date: Tue, 20 Oct 2020 14:11:58 +0100 Subject: [PATCH 24/32] simplify fetchSignInMethodsForEmail by removing SignInMethodQueryResult simplify checkActionCode by removing Operation & ActionCodeDataType --- .../kotlin/dev/gitlive/firebase/auth/auth.kt | 60 +++++++--------- .../kotlin/dev/gitlive/firebase/auth/auth.kt | 54 +++----------- .../kotlin/dev/gitlive/firebase/auth/auth.kt | 53 +++++--------- .../kotlin/dev/gitlive/firebase/auth/auth.kt | 71 ++++++++----------- 4 files changed, 79 insertions(+), 159 deletions(-) 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 3c5658f0c..0c094b239 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 @@ -7,6 +7,7 @@ package dev.gitlive.firebase.auth import com.google.firebase.auth.ActionCodeEmailInfo import com.google.firebase.auth.ActionCodeMultiFactorInfo +import com.google.firebase.auth.ActionCodeResult.* import com.google.firebase.auth.FirebaseAuth.AuthStateListener import dev.gitlive.firebase.Firebase import dev.gitlive.firebase.FirebaseApp @@ -43,13 +44,12 @@ actual class FirebaseAuth internal constructor(val android: com.google.firebase. set(value) { android.setLanguageCode(value) } actual suspend fun applyActionCode(code: String) = android.applyActionCode(code).await().run { Unit } - actual suspend fun checkActionCode(code: String): ActionCodeResult = ActionCodeResult(android.checkActionCode(code).await()) actual suspend fun confirmPasswordReset(code: String, newPassword: String) = android.confirmPasswordReset(code, newPassword).await().run { Unit } actual suspend fun createUserWithEmailAndPassword(email: String, password: String) = AuthResult(android.createUserWithEmailAndPassword(email, password).await()) - actual suspend fun fetchSignInMethodsForEmail(email: String): SignInMethodQueryResult = SignInMethodQueryResult(android.fetchSignInMethodsForEmail(email).await()) + actual suspend fun fetchSignInMethodsForEmail(email: String): List = android.fetchSignInMethodsForEmail(email).await().signInMethods.orEmpty() actual suspend fun sendPasswordResetEmail(email: String, actionCodeSettings: ActionCodeSettings?) { android.sendPasswordResetEmail(email, actionCodeSettings?.toAndroid()).await() @@ -72,6 +72,28 @@ actual class FirebaseAuth internal constructor(val android: com.google.firebase. actual suspend fun updateCurrentUser(user: FirebaseUser) = android.updateCurrentUser(user.android).await().run { Unit } actual suspend fun verifyPasswordResetCode(code: String): String = android.verifyPasswordResetCode(code).await() + + actual suspend fun checkActionCode(code: String): T { + val result = android.checkActionCode(code).await() + @Suppress("UNCHECKED_CAST") + return when(result.operation) { + ERROR -> ActionCodeResult.Error + SIGN_IN_WITH_EMAIL_LINK -> ActionCodeResult.SignInWithEmailLink + VERIFY_EMAIL -> ActionCodeResult.VerifyEmail(result.info!!.email) + PASSWORD_RESET -> ActionCodeResult.PasswordReset(result.info!!.email) + RECOVER_EMAIL -> (result.info as ActionCodeEmailInfo).run { + ActionCodeResult.RecoverEmail(email, previousEmail) + } + VERIFY_BEFORE_CHANGE_EMAIL -> (result.info as ActionCodeEmailInfo).run { + ActionCodeResult.VerifyBeforeChangeEmail(email, previousEmail) + } + REVERT_SECOND_FACTOR_ADDITION -> (result.info as ActionCodeMultiFactorInfo).run { + ActionCodeResult.RevertSecondFactorAddition(email, MultiFactorInfo(multiFactorInfo)) + } + else -> throw UnsupportedOperationException(result.operation.toString()) + } as T + } + } actual class AuthResult internal constructor(val android: com.google.firebase.auth.AuthResult) { @@ -79,40 +101,6 @@ actual class AuthResult internal constructor(val android: com.google.firebase.au get() = android.user?.let { FirebaseUser(it) } } -actual class ActionCodeResult(val android: com.google.firebase.auth.ActionCodeResult) { - actual val operation: Operation - get() = when (android.operation) { - com.google.firebase.auth.ActionCodeResult.PASSWORD_RESET -> Operation.PasswordReset(this) - com.google.firebase.auth.ActionCodeResult.VERIFY_EMAIL -> Operation.VerifyEmail(this) - com.google.firebase.auth.ActionCodeResult.RECOVER_EMAIL -> Operation.RecoverEmail(this) - com.google.firebase.auth.ActionCodeResult.ERROR -> Operation.Error - com.google.firebase.auth.ActionCodeResult.SIGN_IN_WITH_EMAIL_LINK -> Operation.SignInWithEmailLink - com.google.firebase.auth.ActionCodeResult.VERIFY_BEFORE_CHANGE_EMAIL -> Operation.VerifyBeforeChangeEmail(this) - com.google.firebase.auth.ActionCodeResult.REVERT_SECOND_FACTOR_ADDITION -> Operation.RevertSecondFactorAddition(this) - else -> Operation.Error - } -} - -internal actual sealed class ActionCodeDataType { - - actual abstract fun dataForResult(result: ActionCodeResult): T - - actual object Email : ActionCodeDataType() { - override fun dataForResult(result: ActionCodeResult): String = result.android.info!!.email - } - actual object PreviousEmail : ActionCodeDataType() { - override fun dataForResult(result: ActionCodeResult): String = (result.android.info as ActionCodeEmailInfo).previousEmail - } - actual object MultiFactor : ActionCodeDataType() { - override fun dataForResult(result: ActionCodeResult): MultiFactorInfo? = (result.android.info as? ActionCodeMultiFactorInfo)?.multiFactorInfo?.let { MultiFactorInfo(it) } - } -} - -actual class SignInMethodQueryResult(val android: com.google.firebase.auth.SignInMethodQueryResult) { - actual val signInMethods: List - get() = android.signInMethods ?: emptyList() -} - private fun ActionCodeSettings.toAndroid() = com.google.firebase.auth.ActionCodeSettings.newBuilder() .setUrl(url) .also { androidPackageName?.run { it.setAndroidPackageName(packageName, installIfNotAvailable, minimumVersion) } } 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 86c04e38a..f75461106 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 @@ -21,10 +21,10 @@ expect class FirebaseAuth { val idTokenChanged: Flow var languageCode: String suspend fun applyActionCode(code: String) - suspend fun checkActionCode(code: String): ActionCodeResult + suspend fun checkActionCode(code: String): T suspend fun confirmPasswordReset(code: String, newPassword: String) suspend fun createUserWithEmailAndPassword(email: String, password: String): AuthResult - suspend fun fetchSignInMethodsForEmail(email: String): SignInMethodQueryResult + suspend fun fetchSignInMethodsForEmail(email: String): List suspend fun sendPasswordResetEmail(email: String, actionCodeSettings: ActionCodeSettings? = null) suspend fun sendSignInLinkToEmail(email: String, actionCodeSettings: ActionCodeSettings) suspend fun signInWithEmailAndPassword(email: String, password: String): AuthResult @@ -40,48 +40,14 @@ expect class AuthResult { val user: FirebaseUser? } -expect class ActionCodeResult { - val operation: Operation -} - -fun > ActionCodeResult.getData(type: A): T? { - return type.dataForResult(this) -} - -expect class SignInMethodQueryResult { - val signInMethods: List -} - -sealed class Operation { - class PasswordReset(result: ActionCodeResult) : Operation() { - val email: String = ActionCodeDataType.Email.dataForResult(result) - } - class VerifyEmail(result: ActionCodeResult) : Operation() { - val email: String = ActionCodeDataType.Email.dataForResult(result) - } - class RecoverEmail(result: ActionCodeResult) : Operation() { - val email: String = ActionCodeDataType.Email.dataForResult(result) - val previousEmail: String = ActionCodeDataType.PreviousEmail.dataForResult(result) - } - object Error : Operation() - object SignInWithEmailLink : Operation() - class VerifyBeforeChangeEmail(result: ActionCodeResult) : Operation() { - val email: String = ActionCodeDataType.Email.dataForResult(result) - val previousEmail: String = ActionCodeDataType.PreviousEmail.dataForResult(result) - } - class RevertSecondFactorAddition(result: ActionCodeResult) : Operation() { - val email: String = ActionCodeDataType.Email.dataForResult(result) - val multiFactorInfo: MultiFactorInfo? = ActionCodeDataType.MultiFactor.dataForResult(result) - } -} - -internal expect sealed class ActionCodeDataType { - - abstract fun dataForResult(result: ActionCodeResult): T - - object Email : ActionCodeDataType - object PreviousEmail : ActionCodeDataType - object MultiFactor : ActionCodeDataType +sealed class ActionCodeResult { + object Error : ActionCodeResult() + object SignInWithEmailLink : ActionCodeResult() + class PasswordReset internal constructor(val email: String) : ActionCodeResult() + class VerifyEmail internal constructor(val email: String) : ActionCodeResult() + class RecoverEmail internal constructor(val email: String, val previousEmail: String) : ActionCodeResult() + class VerifyBeforeChangeEmail internal constructor(val email: String, val previousEmail: String) : ActionCodeResult() + class RevertSecondFactorAddition internal constructor(val email: String, val multiFactorInfo: MultiFactorInfo?) : ActionCodeResult() } data class ActionCodeSettings( 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 558bba8de..3a849a9f9 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 @@ -8,6 +8,7 @@ import cocoapods.FirebaseAuth.* import dev.gitlive.firebase.Firebase import dev.gitlive.firebase.FirebaseApp import dev.gitlive.firebase.FirebaseException +import dev.gitlive.firebase.auth.ActionCodeResult.* import kotlinx.cinterop.* import kotlinx.coroutines.CompletableDeferred import kotlinx.coroutines.channels.awaitClose @@ -41,16 +42,12 @@ actual class FirebaseAuth internal constructor(val ios: FIRAuth) { set(value) { ios.setLanguageCode(value) } actual suspend fun applyActionCode(code: String) = ios.await { applyActionCode(code, it) }.run { Unit } - actual suspend fun checkActionCode(code: String): ActionCodeResult = ActionCodeResult(ios.awaitExpectedResult { checkActionCode(code, it) }) actual suspend fun confirmPasswordReset(code: String, newPassword: String) = ios.await { confirmPasswordResetWithCode(code, newPassword, it) }.run { Unit } actual suspend fun createUserWithEmailAndPassword(email: String, password: String) = AuthResult(ios.awaitExpectedResult { createUserWithEmail(email = email, password = password, completion = it) }) - actual suspend fun fetchSignInMethodsForEmail(email: String): SignInMethodQueryResult { - val signInMethods: List<*>? = ios.awaitResult { fetchSignInMethodsForEmail(email, it) } - return SignInMethodQueryResult(signInMethods?.mapNotNull { it as String } ?: emptyList()) - } + actual suspend fun fetchSignInMethodsForEmail(email: String) = ios.awaitResult { fetchSignInMethodsForEmail(email, it) }.orEmpty() actual suspend fun sendPasswordResetEmail(email: String, actionCodeSettings: ActionCodeSettings?) { ios.await { actionCodeSettings?.let { actionSettings -> sendPasswordResetWithEmail(email, actionSettings.toIos(), it) } ?: sendPasswordResetWithEmail(email = email, completion = it) } @@ -74,6 +71,21 @@ actual class FirebaseAuth internal constructor(val ios: FIRAuth) { actual suspend fun updateCurrentUser(user: FirebaseUser) = ios.await { updateCurrentUser(user.ios, it) }.run { Unit } actual suspend fun verifyPasswordResetCode(code: String): String = ios.awaitExpectedResult { verifyPasswordResetCode(code, it) } + + actual suspend fun checkActionCode(code: String): T { + val result = ios.awaitExpectedResult { checkActionCode(code, it) } + @Suppress("UNCHECKED_CAST") + return when(result.operation) { + FIRActionCodeOperationUnknown -> Error + FIRActionCodeOperationEmailLink -> SignInWithEmailLink + FIRActionCodeOperationVerifyEmail -> VerifyEmail(result.email!!) + FIRActionCodeOperationPasswordReset -> PasswordReset(result.email!!) + FIRActionCodeOperationRecoverEmail -> RecoverEmail(result.email!!, result.previousEmail!!) + FIRActionCodeOperationVerifyAndChangeEmail -> VerifyBeforeChangeEmail(result.email!!, result.previousEmail!!) + FIRActionCodeOperationRevertSecondFactorAddition -> RevertSecondFactorAddition(result.email!!, null) + else -> throw UnsupportedOperationException(result.operation.toString()) + } as T + } } actual class AuthResult internal constructor(val ios: FIRAuthDataResult) { @@ -81,37 +93,6 @@ actual class AuthResult internal constructor(val ios: FIRAuthDataResult) { get() = FirebaseUser(ios.user) } -actual class ActionCodeResult(val ios: FIRActionCodeInfo) { - actual val operation: Operation - get() = when (ios.operation) { - FIRActionCodeOperationPasswordReset -> Operation.PasswordReset(this) - FIRActionCodeOperationVerifyEmail -> Operation.VerifyEmail(this) - FIRActionCodeOperationRecoverEmail -> Operation.RecoverEmail(this) - FIRActionCodeOperationUnknown-> Operation.Error - FIRActionCodeOperationEmailLink -> Operation.SignInWithEmailLink - FIRActionCodeOperationVerifyAndChangeEmail -> Operation.VerifyBeforeChangeEmail(this) - FIRActionCodeOperationRevertSecondFactorAddition -> Operation.RevertSecondFactorAddition(this) - else -> Operation.Error - } -} - -internal actual sealed class ActionCodeDataType { - - actual abstract fun dataForResult(result: ActionCodeResult): T - - actual object Email : ActionCodeDataType() { - override fun dataForResult(result: ActionCodeResult): String = result.ios.email!! - } - actual object PreviousEmail : ActionCodeDataType() { - override fun dataForResult(result: ActionCodeResult): String = result.ios.previousEmail!! - } - actual object MultiFactor : ActionCodeDataType() { - override fun dataForResult(result: ActionCodeResult): MultiFactorInfo? = null - } -} - -actual class SignInMethodQueryResult(actual val signInMethods: List) - private fun ActionCodeSettings.toIos() = FIRActionCodeSettings().let { it.URL = NSURL.URLWithString(url) androidPackageName?.run { it.setAndroidPackageName(androidPackageName, installIfNotAvailable, minimumVersion) } 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 092c8c712..c78e7c11c 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 @@ -38,13 +38,12 @@ actual class FirebaseAuth internal constructor(val js: firebase.auth.Auth) { set(value) { js.languageCode = value } actual suspend fun applyActionCode(code: String) = rethrow { js.applyActionCode(code).await() } - actual suspend fun checkActionCode(code: String): ActionCodeResult = rethrow { ActionCodeResult(js.checkActionCode(code).await()) } actual suspend fun confirmPasswordReset(code: String, newPassword: String) = rethrow { js.confirmPasswordReset(code, newPassword).await() } actual suspend fun createUserWithEmailAndPassword(email: String, password: String) = rethrow { AuthResult(js.createUserWithEmailAndPassword(email, password).await()) } - actual suspend fun fetchSignInMethodsForEmail(email: String): SignInMethodQueryResult = rethrow { SignInMethodQueryResult(js.fetchSignInMethodsForEmail(email).await().asList()) } + actual suspend fun fetchSignInMethodsForEmail(email: String): List = rethrow { js.fetchSignInMethodsForEmail(email).await().asList() } actual suspend fun sendPasswordResetEmail(email: String, actionCodeSettings: ActionCodeSettings?) = rethrow { js.sendPasswordResetEmail(email, actionCodeSettings?.toJson()).await() } @@ -55,11 +54,11 @@ actual class FirebaseAuth internal constructor(val js: firebase.auth.Auth) { actual suspend fun signInWithEmailAndPassword(email: String, password: String) = rethrow { AuthResult(js.signInWithEmailAndPassword(email, password).await()) } - actual suspend fun signInWithCustomToken(token: String) - = rethrow { AuthResult(js.signInWithCustomToken(token).await()) } + actual suspend fun signInWithCustomToken(token: String) = + rethrow { AuthResult(js.signInWithCustomToken(token).await()) } - actual suspend fun signInAnonymously() - = rethrow { AuthResult(js.signInAnonymously().await()) } + actual suspend fun signInAnonymously() = + rethrow { AuthResult(js.signInAnonymously().await()) } actual suspend fun signInWithCredential(authCredential: AuthCredential) = rethrow { AuthResult(js.signInWithCredential(authCredential.js).await()) } @@ -67,14 +66,30 @@ actual class FirebaseAuth internal constructor(val js: firebase.auth.Auth) { actual suspend fun signOut() = rethrow { js.signOut().await() } actual suspend fun updateCurrentUser(user: FirebaseUser) = - rethrow { - js.updateCurrentUser(user.js).await() - } - actual suspend fun verifyPasswordResetCode(code: String): String = - rethrow { - js.verifyPasswordResetCode(code).await() - } + rethrow { js.updateCurrentUser(user.js).await() } + actual suspend fun verifyPasswordResetCode(code: String): String = + rethrow { js.verifyPasswordResetCode(code).await() } + + actual suspend fun checkActionCode(code: String): T = rethrow { + val result = js.checkActionCode(code).await() + @Suppress("UNCHECKED_CAST") + return when(result.operation) { + "EMAIL_SIGNIN" -> ActionCodeResult.SignInWithEmailLink + "VERIFY_EMAIL" -> ActionCodeResult.VerifyEmail(result.data.email!!) + "PASSWORD_RESET" -> ActionCodeResult.PasswordReset(result.data.email!!) + "RECOVER_EMAIL" -> ActionCodeResult.RecoverEmail(result.data.email!!, result.data.previousEmail!!) + "VERIFY_AND_CHANGE_EMAIL" -> ActionCodeResult.VerifyBeforeChangeEmail( + result.data.email!!, + result.data.previousEmail!! + ) + "REVERT_SECOND_FACTOR_ADDITION" -> ActionCodeResult.RevertSecondFactorAddition( + result.data.email!!, + result.data.multiFactorInfo?.let { MultiFactorInfo(it) } + ) + else -> throw UnsupportedOperationException(result.operation) + } as T + } } actual class AuthResult internal constructor(val js: firebase.auth.AuthResult) { @@ -82,36 +97,6 @@ actual class AuthResult internal constructor(val js: firebase.auth.AuthResult) { get() = rethrow { js.user?.let { FirebaseUser(it) } } } -actual class ActionCodeResult(val js: firebase.auth.ActionCodeInfo) { - actual val operation: Operation - get() = when (js.operation) { - "PASSWORD_RESET" -> Operation.PasswordReset(this) - "VERIFY_EMAIL" -> Operation.VerifyEmail(this) - "RECOVER_EMAIL" -> Operation.RecoverEmail(this) - "EMAIL_SIGNIN" -> Operation.SignInWithEmailLink - "VERIFY_AND_CHANGE_EMAIL" -> Operation.VerifyBeforeChangeEmail(this) - "REVERT_SECOND_FACTOR_ADDITION" -> Operation.RevertSecondFactorAddition(this) - else -> Operation.Error - } -} - -internal actual sealed class ActionCodeDataType { - - actual abstract fun dataForResult(result: ActionCodeResult): T - - actual object Email : ActionCodeDataType() { - override fun dataForResult(result: ActionCodeResult): String = result.js.data.email!! - } - actual object PreviousEmail : ActionCodeDataType() { - override fun dataForResult(result: ActionCodeResult): String = result.js.data.previousEmail!! - } - actual object MultiFactor : ActionCodeDataType() { - override fun dataForResult(result: ActionCodeResult): MultiFactorInfo? = result.js.data.multiFactorInfo?.let { MultiFactorInfo(it) } - } -} - -actual class SignInMethodQueryResult(actual val signInMethods: List) - private fun ActionCodeSettings.toJson() = json( "android" to (androidPackageName?.run { json("installApp" to installIfNotAvailable, "minimumVersion" to minimumVersion, "packageName" to packageName) } ?: undefined), "dynamicLinkDomain" to (dynamicLinkDomain ?: undefined), From a4af2d0ecd7abdb5e36973569c07551ecbae631d Mon Sep 17 00:00:00 2001 From: Andrew Reed Date: Tue, 20 Oct 2020 16:59:54 +0100 Subject: [PATCH 25/32] Added fix to script. --- .github/workflows/publish.yml | 2 +- .github/workflows/pull_request.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index f19c050c3..4f6afa6f9 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -25,7 +25,7 @@ jobs: - name: Grant execute permission for gradlew run: chmod +x gradlew - name: Install Homebrew - run: ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" + run: ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)" - name: Install Carthage run: brew install carthage - name: Publish diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index 619fb3670..358311245 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -21,7 +21,7 @@ jobs: - name: Grant execute permission for gradlew run: chmod +x gradlew - name: Install Homebrew - run: ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" + run: ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)" - name: Install Carthage run: brew install carthage - name: Assemble From 823ab905e30025a663468dd0c310261326c2a49a Mon Sep 17 00:00:00 2001 From: Andrew Reed Date: Tue, 20 Oct 2020 17:03:32 +0100 Subject: [PATCH 26/32] Adjusted script --- .github/workflows/publish.yml | 2 +- .github/workflows/pull_request.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 4f6afa6f9..0d22b14a9 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -25,7 +25,7 @@ jobs: - name: Grant execute permission for gradlew run: chmod +x gradlew - name: Install Homebrew - run: ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)" + run: /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)" - name: Install Carthage run: brew install carthage - name: Publish diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index 358311245..6762edf79 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -21,7 +21,7 @@ jobs: - name: Grant execute permission for gradlew run: chmod +x gradlew - name: Install Homebrew - run: ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)" + run: /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)" - name: Install Carthage run: brew install carthage - name: Assemble From 5211edbf0fc52b16f5041aba77b0586b5baade2a Mon Sep 17 00:00:00 2001 From: Andrew Reed Date: Tue, 20 Oct 2020 17:06:06 +0100 Subject: [PATCH 27/32] Added check of homebrew. --- .github/workflows/pull_request.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index 6762edf79..eed867b9e 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -21,7 +21,7 @@ jobs: - name: Grant execute permission for gradlew run: chmod +x gradlew - name: Install Homebrew - run: /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)" + run: brew -v - name: Install Carthage run: brew install carthage - name: Assemble From 45ae540696b7c9dfc8f66a8f180c5ce7926524d6 Mon Sep 17 00:00:00 2001 From: Andrew Reed Date: Tue, 20 Oct 2020 17:07:44 +0100 Subject: [PATCH 28/32] Removed brew install due to being already installed on github machines. --- .github/workflows/publish.yml | 2 -- .github/workflows/pull_request.yml | 2 -- 2 files changed, 4 deletions(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 0d22b14a9..a5bfdc1a9 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -24,8 +24,6 @@ jobs: arguments: :updateVersions - name: Grant execute permission for gradlew run: chmod +x gradlew - - name: Install Homebrew - run: /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)" - name: Install Carthage run: brew install carthage - name: Publish diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index eed867b9e..ea96223f1 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -20,8 +20,6 @@ jobs: java-version: 1.8 - name: Grant execute permission for gradlew run: chmod +x gradlew - - name: Install Homebrew - run: brew -v - name: Install Carthage run: brew install carthage - name: Assemble From e224920fd4abe90b6dcf8e439dcb7be663856318 Mon Sep 17 00:00:00 2001 From: nbransby Date: Tue, 20 Oct 2020 20:43:07 +0100 Subject: [PATCH 29/32] rename all credentialWithX functions to just credential use single credential function in OAuthProvider with optional params --- .../kotlin/dev/gitlive/firebase/auth/auth.kt | 2 +- .../dev/gitlive/firebase/auth/credentials.kt | 43 ++++++---------- .../kotlin/dev/gitlive/firebase/auth/user.kt | 7 +-- .../dev/gitlive/firebase/auth/credentials.kt | 18 +++---- .../kotlin/dev/gitlive/firebase/auth/auth.kt | 2 +- .../dev/gitlive/firebase/auth/credentials.kt | 28 +++++++---- .../kotlin/dev/gitlive/firebase/auth/user.kt | 24 ++++++--- .../kotlin/dev/gitlive/firebase/auth/auth.kt | 4 +- .../dev/gitlive/firebase/auth/credentials.kt | 50 +++++++++---------- .../kotlin/dev/gitlive/firebase/auth/user.kt | 4 +- .../kotlin/dev/gitlive/firebase/externals.kt | 10 ++-- 11 files changed, 95 insertions(+), 97 deletions(-) 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 0c094b239..115a6450c 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 @@ -101,7 +101,7 @@ actual class AuthResult internal constructor(val android: com.google.firebase.au get() = android.user?.let { FirebaseUser(it) } } -private fun ActionCodeSettings.toAndroid() = com.google.firebase.auth.ActionCodeSettings.newBuilder() +internal fun ActionCodeSettings.toAndroid() = com.google.firebase.auth.ActionCodeSettings.newBuilder() .setUrl(url) .also { androidPackageName?.run { it.setAndroidPackageName(packageName, installIfNotAvailable, minimumVersion) } } .also { dynamicLinkDomain?.run { it.setDynamicLinkDomain(this) } } diff --git a/firebase-auth/src/androidMain/kotlin/dev/gitlive/firebase/auth/credentials.kt b/firebase-auth/src/androidMain/kotlin/dev/gitlive/firebase/auth/credentials.kt index 7da683b4c..fbd387321 100644 --- a/firebase-auth/src/androidMain/kotlin/dev/gitlive/firebase/auth/credentials.kt +++ b/firebase-auth/src/androidMain/kotlin/dev/gitlive/firebase/auth/credentials.kt @@ -6,6 +6,7 @@ package dev.gitlive.firebase.auth import android.app.Activity import com.google.firebase.FirebaseException +import com.google.firebase.auth.OAuthProvider import com.google.firebase.auth.PhoneAuthProvider import kotlinx.coroutines.CompletableDeferred import kotlinx.coroutines.coroutineScope @@ -23,48 +24,34 @@ actual class PhoneAuthCredential(override val android: com.google.firebase.auth. actual class OAuthCredential(override val android: com.google.firebase.auth.OAuthCredential) : AuthCredential(android) actual object EmailAuthProvider { - actual fun credentialWithEmail( + actual fun credential( email: String, password: String ): AuthCredential = AuthCredential(com.google.firebase.auth.EmailAuthProvider.getCredential(email, password)) } actual object FacebookAuthProvider { - actual fun credentialWithAccessToken(accessToken: String): AuthCredential = AuthCredential(com.google.firebase.auth.FacebookAuthProvider.getCredential(accessToken)) + actual fun credential(accessToken: String): AuthCredential = AuthCredential(com.google.firebase.auth.FacebookAuthProvider.getCredential(accessToken)) } actual object GithubAuthProvider { - actual fun credentialWithToken(token: String): AuthCredential = AuthCredential(com.google.firebase.auth.GithubAuthProvider.getCredential(token)) + actual fun credential(token: String): AuthCredential = AuthCredential(com.google.firebase.auth.GithubAuthProvider.getCredential(token)) } actual object GoogleAuthProvider { - actual fun credentialWithIDAndAccessToken(idToken: String, accessToken: String): AuthCredential = AuthCredential(com.google.firebase.auth.GoogleAuthProvider.getCredential(idToken, accessToken)) + actual fun credential(idToken: String, accessToken: String): AuthCredential = AuthCredential(com.google.firebase.auth.GoogleAuthProvider.getCredential(idToken, accessToken)) } actual class OAuthProvider(val android: com.google.firebase.auth.OAuthProvider.Builder, private val auth: FirebaseAuth) { actual constructor(provider: String, auth: FirebaseAuth) : this(com.google.firebase.auth.OAuthProvider.newBuilder(provider, auth.android), auth) actual companion object { - actual fun credentialsWithAccessToken(providerId: String, accessToken: String): AuthCredential = createCredentials(providerId) { - this.accessToken = accessToken - } - actual fun credentialsWithIDAndAccessToken(providerId: String, idToken: String, accessToken: String): AuthCredential = createCredentials(providerId) { - setIdToken(idToken) - this.accessToken = accessToken - } - actual fun credentialsWithIDRawNonceAndAccessToken(providerId: String, idToken: String, rawNonce: String, accessToken: String): AuthCredential = createCredentials(providerId) { - setIdTokenWithRawNonce(idToken, rawNonce) - this.accessToken = accessToken - } - actual fun credentialsWithIDAndRawNonce(providerId: String, idToken: String, rawNonce: String): AuthCredential = createCredentials(providerId) { - setIdTokenWithRawNonce(idToken, rawNonce) - } - - private fun createCredentials(providerId: String, block: com.google.firebase.auth.OAuthProvider.CredentialBuilder.() -> Unit): AuthCredential { - val credential = com.google.firebase.auth.OAuthProvider.newCredentialBuilder(providerId).apply { - block() - }.build() - return (credential as? com.google.firebase.auth.OAuthCredential)?.let { OAuthCredential(it) } ?: AuthCredential(credential) + actual fun credential(providerId: String, accessToken: String?, idToken: String?, rawNonce: String?): OAuthCredential { + val builder = OAuthProvider.newCredentialBuilder(providerId) + accessToken?.let { builder.accessToken = it } + idToken?.let { builder.idToken = it } + rawNonce?.let { builder.setIdTokenWithRawNonce(idToken!!, it) } + return OAuthCredential(builder.build() as com.google.firebase.auth.OAuthCredential) } } @@ -87,7 +74,7 @@ actual class PhoneAuthProvider(val android: com.google.firebase.auth.PhoneAuthPr actual constructor(auth: FirebaseAuth) : this(com.google.firebase.auth.PhoneAuthProvider.getInstance(auth.android)) - actual fun credentialWithVerificationIdAndSmsCode(verificationId: String, smsCode: String): PhoneAuthCredential = PhoneAuthCredential(com.google.firebase.auth.PhoneAuthProvider.getCredential(verificationId, smsCode)) + actual fun credential(verificationId: String, smsCode: String): PhoneAuthCredential = PhoneAuthCredential(com.google.firebase.auth.PhoneAuthProvider.getCredential(verificationId, smsCode)) actual suspend fun verifyPhoneNumber(phoneNumber: String, verificationProvider: PhoneVerificationProvider): AuthCredential = coroutineScope { val response = CompletableDeferred>() val callback = object : @@ -101,9 +88,7 @@ actual class PhoneAuthProvider(val android: com.google.firebase.auth.PhoneAuthPr launch { val code = verificationProvider.getVerificationCode() try { - val credentials = - credentialWithVerificationIdAndSmsCode(verificationId, code) - response.complete(Result.success(credentials)) + response.complete(Result.success(credential(verificationId, code))) } catch (e: Exception) { response.complete(Result.failure(e)) } @@ -134,5 +119,5 @@ actual interface PhoneVerificationProvider { } actual object TwitterAuthProvider { - actual fun credentialWithTokenAndSecret(token: String, secret: String): AuthCredential = AuthCredential(com.google.firebase.auth.TwitterAuthProvider.getCredential(token, secret)) + actual fun credential(token: String, secret: String): AuthCredential = AuthCredential(com.google.firebase.auth.TwitterAuthProvider.getCredential(token, secret)) } diff --git a/firebase-auth/src/androidMain/kotlin/dev/gitlive/firebase/auth/user.kt b/firebase-auth/src/androidMain/kotlin/dev/gitlive/firebase/auth/user.kt index 20aa61055..e8b6297b3 100644 --- a/firebase-auth/src/androidMain/kotlin/dev/gitlive/firebase/auth/user.kt +++ b/firebase-auth/src/androidMain/kotlin/dev/gitlive/firebase/auth/user.kt @@ -38,8 +38,8 @@ actual class FirebaseUser internal constructor(val android: com.google.firebase. actual suspend fun reauthenticate(credential: AuthCredential) = android.reauthenticate(credential.android).await().run { Unit } actual suspend fun reauthenticateAndRetrieveData(credential: AuthCredential): AuthResult = AuthResult(android.reauthenticateAndRetrieveData(credential.android).await()) actual suspend fun sendEmailVerification(actionCodeSettings: ActionCodeSettings?) { - val request = actionCodeSettings?.android?.let { android.sendEmailVerification(it) } ?: android.sendEmailVerification() - request.await().run { Unit } + val request = actionCodeSettings?.let { android.sendEmailVerification(it.toAndroid()) } ?: android.sendEmailVerification() + request.await() } actual suspend fun unlink(provider: String): FirebaseUser? = android.unlink(provider).await().user?.let { FirebaseUser(it) } actual suspend fun updateEmail(email: String) = android.updateEmail(email).await().run { Unit } @@ -52,7 +52,8 @@ actual class FirebaseUser internal constructor(val android: com.google.firebase. }.build() android.updateProfile(request).await() } - actual suspend fun verifyBeforeUpdateEmail(newEmail: String, actionCodeSettings: ActionCodeSettings?) = android.verifyBeforeUpdateEmail(newEmail, actionCodeSettings?.android).await().run { Unit } + actual suspend fun verifyBeforeUpdateEmail(newEmail: String, actionCodeSettings: ActionCodeSettings?) = + android.verifyBeforeUpdateEmail(newEmail, actionCodeSettings?.toAndroid()).await().run { Unit } } actual class UserInfo(val android: com.google.firebase.auth.UserInfo) { diff --git a/firebase-auth/src/commonMain/kotlin/dev/gitlive/firebase/auth/credentials.kt b/firebase-auth/src/commonMain/kotlin/dev/gitlive/firebase/auth/credentials.kt index c0d88a703..320cad47f 100644 --- a/firebase-auth/src/commonMain/kotlin/dev/gitlive/firebase/auth/credentials.kt +++ b/firebase-auth/src/commonMain/kotlin/dev/gitlive/firebase/auth/credentials.kt @@ -14,27 +14,24 @@ expect class PhoneAuthCredential : AuthCredential expect class OAuthCredential : AuthCredential expect object EmailAuthProvider { - fun credentialWithEmail(email: String, password: String): AuthCredential + fun credential(email: String, password: String): AuthCredential } expect object FacebookAuthProvider { - fun credentialWithAccessToken(accessToken: String): AuthCredential + fun credential(accessToken: String): AuthCredential } expect object GithubAuthProvider { - fun credentialWithToken(token: String): AuthCredential + fun credential(token: String): AuthCredential } expect object GoogleAuthProvider { - fun credentialWithIDAndAccessToken(idToken: String, accessToken: String): AuthCredential + fun credential(idToken: String, accessToken: String): AuthCredential } expect class OAuthProvider constructor(provider: String, auth: FirebaseAuth = Firebase.auth) { companion object { - fun credentialsWithAccessToken(providerId: String, accessToken: String): AuthCredential - fun credentialsWithIDAndAccessToken(providerId: String, idToken: String, accessToken: String): AuthCredential - fun credentialsWithIDRawNonceAndAccessToken(providerId: String, idToken: String, rawNonce: String, accessToken: String): AuthCredential - fun credentialsWithIDAndRawNonce(providerId: String, idToken: String, rawNonce: String): AuthCredential + fun credential(providerId: String, accessToken: String? = null, idToken: String? = null, rawNonce: String? = null): OAuthCredential } fun addScope(vararg scope: String) @@ -46,13 +43,12 @@ expect class OAuthProvider constructor(provider: String, auth: FirebaseAuth = Fi expect class SignInProvider expect class PhoneAuthProvider constructor(auth: FirebaseAuth = Firebase.auth) { - fun credentialWithVerificationIdAndSmsCode(verificationId: String, smsCode: String): PhoneAuthCredential + fun credential(verificationId: String, smsCode: String): PhoneAuthCredential suspend fun verifyPhoneNumber(phoneNumber: String, verificationProvider: PhoneVerificationProvider): AuthCredential - } expect interface PhoneVerificationProvider expect object TwitterAuthProvider { - fun credentialWithTokenAndSecret(token: String, secret: String): AuthCredential + fun credential(token: String, secret: String): AuthCredential } 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 3a849a9f9..cd356f439 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 @@ -93,7 +93,7 @@ actual class AuthResult internal constructor(val ios: FIRAuthDataResult) { get() = FirebaseUser(ios.user) } -private fun ActionCodeSettings.toIos() = FIRActionCodeSettings().let { +internal fun ActionCodeSettings.toIos() = FIRActionCodeSettings().let { it.URL = NSURL.URLWithString(url) androidPackageName?.run { it.setAndroidPackageName(androidPackageName, installIfNotAvailable, minimumVersion) } it.dynamicLinkDomain = dynamicLinkDomain diff --git a/firebase-auth/src/iosMain/kotlin/dev/gitlive/firebase/auth/credentials.kt b/firebase-auth/src/iosMain/kotlin/dev/gitlive/firebase/auth/credentials.kt index 8be084064..3045e6832 100644 --- a/firebase-auth/src/iosMain/kotlin/dev/gitlive/firebase/auth/credentials.kt +++ b/firebase-auth/src/iosMain/kotlin/dev/gitlive/firebase/auth/credentials.kt @@ -15,7 +15,7 @@ actual class PhoneAuthCredential(override val ios: FIRPhoneAuthCredential) : Aut actual class OAuthCredential(override val ios: FIROAuthCredential) : AuthCredential(ios) actual object EmailAuthProvider { - actual fun credentialWithEmail( + actual fun credential( email: String, password: String ): AuthCredential = @@ -23,31 +23,37 @@ actual object EmailAuthProvider { } actual object FacebookAuthProvider { - actual fun credentialWithAccessToken(accessToken: String): AuthCredential = AuthCredential(FIRFacebookAuthProvider.credentialWithAccessToken(accessToken)) + actual fun credential(accessToken: String): AuthCredential = AuthCredential(FIRFacebookAuthProvider.credentialWithAccessToken(accessToken)) } actual object GithubAuthProvider { - actual fun credentialWithToken(token: String): AuthCredential = AuthCredential(FIRGitHubAuthProvider.credentialWithToken(token)) + actual fun credential(token: String): AuthCredential = AuthCredential(FIRGitHubAuthProvider.credentialWithToken(token)) } actual object GoogleAuthProvider { - actual fun credentialWithIDAndAccessToken(idToken: String, accessToken: String): AuthCredential = AuthCredential(FIRGoogleAuthProvider.credentialWithIDToken(idToken, accessToken)) + actual fun credential(idToken: String, accessToken: String): AuthCredential = AuthCredential(FIRGoogleAuthProvider.credentialWithIDToken(idToken, accessToken)) } actual class OAuthProvider(val ios: FIROAuthProvider, private val auth: FirebaseAuth) { actual constructor(provider: String, auth: FirebaseAuth) : this(FIROAuthProvider.providerWithProviderID(provider, auth.ios), auth) actual companion object { - actual fun credentialsWithAccessToken(providerId: String, accessToken: String): AuthCredential = AuthCredential(FIROAuthProvider.credentialWithProviderID(providerId, accessToken)) - actual fun credentialsWithIDAndAccessToken(providerId: String, idToken: String, accessToken: String): AuthCredential = AuthCredential(FIROAuthProvider.credentialWithProviderID(providerID = providerId, IDToken = idToken, accessToken = accessToken)) - actual fun credentialsWithIDRawNonceAndAccessToken(providerId: String, idToken: String, rawNonce: String, accessToken: String): AuthCredential = AuthCredential(FIROAuthProvider.credentialWithProviderID(providerID = providerId, IDToken = idToken, rawNonce = rawNonce, accessToken = accessToken)) - actual fun credentialsWithIDAndRawNonce(providerId: String, idToken: String, rawNonce: String): AuthCredential = AuthCredential(FIROAuthProvider.credentialWithProviderID(providerID = providerId, IDToken = idToken, rawNonce = rawNonce)) + actual fun credential(providerId: String, accessToken: String?, idToken: String?, rawNonce: String?): OAuthCredential { + val credential = when { + idToken == null -> FIROAuthProvider.credentialWithProviderID(providerId = providerId, accessToken = accessToken!!) + accessToken == null -> FIROAuthProvider.credentialWithProviderID(providerID = providerId, IDToken = idToken, rawNonce = rawNonce!!) + rawNonce == null -> FIROAuthProvider.credentialWithProviderID(providerID = providerId, IDToken = idToken, accessToken = accessToken) + else -> FIROAuthProvider.credentialWithProviderID(providerID = providerId, IDToken = idToken, rawNonce = rawNonce, accessToken = accessToken) + } + return OAuthCredential(credential as FIROAuthCredential) + } } actual fun addScope(vararg scope: String) { val scopes = ios.scopes?.mapNotNull { it as? String } ?: emptyList() ios.setScopes(scopes + scope.asList()) } + actual fun setCustomParameters(parameters: Map) { ios.setCustomParameters(emptyMap() + parameters) } @@ -72,11 +78,11 @@ actual class PhoneAuthProvider(val ios: FIRPhoneAuthProvider) { actual constructor(auth: FirebaseAuth) : this(FIRPhoneAuthProvider.providerWithAuth(auth.ios)) - actual fun credentialWithVerificationIdAndSmsCode(verificationId: String, smsCode: String): PhoneAuthCredential = PhoneAuthCredential(ios.credentialWithVerificationID(verificationId, smsCode)) + actual fun credential(verificationId: String, smsCode: String): PhoneAuthCredential = PhoneAuthCredential(ios.credentialWithVerificationID(verificationId, smsCode)) actual suspend fun verifyPhoneNumber(phoneNumber: String, verificationProvider: PhoneVerificationProvider): AuthCredential { val verificationId: String = ios.awaitExpectedResult { ios.verifyPhoneNumber(phoneNumber, verificationProvider.delegate, it) } val verificationCode = verificationProvider.getVerificationCode() - return credentialWithVerificationIdAndSmsCode(verificationId, verificationCode) + return credential(verificationId, verificationCode) } } @@ -86,5 +92,5 @@ actual interface PhoneVerificationProvider { } actual object TwitterAuthProvider { - actual fun credentialWithTokenAndSecret(token: String, secret: String): AuthCredential = AuthCredential(FIRTwitterAuthProvider.credentialWithToken(token, secret)) + actual fun credential(token: String, secret: String): AuthCredential = AuthCredential(FIRTwitterAuthProvider.credentialWithToken(token, secret)) } \ No newline at end of file diff --git a/firebase-auth/src/iosMain/kotlin/dev/gitlive/firebase/auth/user.kt b/firebase-auth/src/iosMain/kotlin/dev/gitlive/firebase/auth/user.kt index 1432cd749..5a23e7909 100644 --- a/firebase-auth/src/iosMain/kotlin/dev/gitlive/firebase/auth/user.kt +++ b/firebase-auth/src/iosMain/kotlin/dev/gitlive/firebase/auth/user.kt @@ -30,18 +30,28 @@ actual class FirebaseUser internal constructor(val ios: FIRUser) { get() = ios.providerData.mapNotNull { provider -> (provider as? FIRUserInfoProtocol)?.let { UserInfo(it) } } actual val providerId: String get() = ios.providerID + actual suspend fun delete() = ios.await { deleteWithCompletion(it) }.run { Unit } + actual suspend fun reload() = ios.await { reloadWithCompletion(it) }.run { Unit } - actual suspend fun getIdToken(forceRefresh: Boolean): String? = ios.awaitResult { getIDTokenForcingRefresh(forceRefresh, it) } - actual suspend fun linkWithCredential(credential: AuthCredential): AuthResult = AuthResult(ios.awaitExpectedResult { linkWithCredential(credential.ios, it) }) - actual suspend fun reauthenticate(credential: AuthCredential) { - val result: FIRAuthDataResult = ios.awaitExpectedResult { reauthenticateWithCredential(credential.ios, it) } - } - actual suspend fun reauthenticateAndRetrieveData(credential: AuthCredential): AuthResult = AuthResult(ios.awaitExpectedResult { reauthenticateWithCredential(credential.ios, it) }) + + actual suspend fun getIdToken(forceRefresh: Boolean): String? = + ios.awaitResult { getIDTokenForcingRefresh(forceRefresh, it) } + + actual suspend fun linkWithCredential(credential: AuthCredential): AuthResult = + AuthResult(ios.awaitExpectedResult { linkWithCredential(credential.ios, it) }) + + actual suspend fun reauthenticate(credential: AuthCredential) = + ios.awaitExpectedResult { reauthenticateWithCredential(credential.ios, it) }.run { Unit } + + actual suspend fun reauthenticateAndRetrieveData(credential: AuthCredential): AuthResult = + AuthResult(ios.awaitExpectedResult { reauthenticateAndRetrieveDataWithCredential(credential.ios, it) }) actual suspend fun sendEmailVerification(actionCodeSettings: ActionCodeSettings?) = ios.await { - actionCodeSettings?.let { actionSettings -> sendEmailVerificationWithActionCodeSettings(actionSettings.ios, it) } ?: sendEmailVerificationWithCompletion(it) + actionCodeSettings?.let { settings -> sendEmailVerificationWithActionCodeSettings(settings.toIos(), it) } + ?: sendEmailVerificationWithCompletion(it) }.run { Unit } + actual suspend fun unlink(provider: String): FirebaseUser? { val user: FIRUser? = ios.awaitResult { unlinkFromProvider(provider, it) } return user?.let { 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 8a3618167..5989055e9 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 @@ -4,6 +4,8 @@ package dev.gitlive.firebase.auth +import dev.gitlive.firebase.* +import kotlinx.coroutines.await import kotlinx.coroutines.channels.awaitClose import kotlinx.coroutines.flow.callbackFlow import kotlin.js.json @@ -97,7 +99,7 @@ actual class AuthResult internal constructor(val js: firebase.auth.AuthResult) { get() = rethrow { js.user?.let { FirebaseUser(it) } } } -private fun ActionCodeSettings.toJson() = json( +internal fun ActionCodeSettings.toJson() = json( "android" to (androidPackageName?.run { json("installApp" to installIfNotAvailable, "minimumVersion" to minimumVersion, "packageName" to packageName) } ?: undefined), "dynamicLinkDomain" to (dynamicLinkDomain ?: undefined), "handleCodeInApp" to canHandleCodeInApp, diff --git a/firebase-auth/src/jsMain/kotlin/dev/gitlive/firebase/auth/credentials.kt b/firebase-auth/src/jsMain/kotlin/dev/gitlive/firebase/auth/credentials.kt index 31bccfb4a..15baf5eb6 100644 --- a/firebase-auth/src/jsMain/kotlin/dev/gitlive/firebase/auth/credentials.kt +++ b/firebase-auth/src/jsMain/kotlin/dev/gitlive/firebase/auth/credentials.kt @@ -2,6 +2,8 @@ package dev.gitlive.firebase.auth import dev.gitlive.firebase.firebase import kotlinx.coroutines.await +import kotlin.js.Json +import kotlin.js.json actual open class AuthCredential(val js: firebase.auth.AuthCredential) { actual val providerId: String @@ -12,44 +14,40 @@ actual class PhoneAuthCredential(js: firebase.auth.AuthCredential) : AuthCredent actual class OAuthCredential(js: firebase.auth.AuthCredential) : AuthCredential(js) actual object EmailAuthProvider { - actual fun credentialWithEmail( - email: String, - password: String - ): AuthCredential = AuthCredential(firebase.auth.EmailAuthProvider.credential(email, password)) + actual fun credential(email: String, password: String): AuthCredential = + AuthCredential(firebase.auth.EmailAuthProvider.credential(email, password)) } actual object FacebookAuthProvider { - actual fun credentialWithAccessToken(accessToken: String): AuthCredential = AuthCredential(firebase.auth.FacebookAuthProvider.credential(accessToken)) + actual fun credential(accessToken: String): AuthCredential = + AuthCredential(firebase.auth.FacebookAuthProvider.credential(accessToken)) } actual object GithubAuthProvider { - actual fun credentialWithToken(token: String): AuthCredential = AuthCredential(firebase.auth.GithubAuthProvider.credential(token)) + actual fun credential(token: String): AuthCredential = + AuthCredential(firebase.auth.GithubAuthProvider.credential(token)) } actual object GoogleAuthProvider { - actual fun credentialWithIDAndAccessToken(idToken: String, accessToken: String): AuthCredential = AuthCredential(firebase.auth.GoogleAuthProvider.credential(idToken, accessToken)) + actual fun credential(idToken: String, accessToken: String): AuthCredential = + AuthCredential(firebase.auth.GoogleAuthProvider.credential(idToken, accessToken)) } actual class OAuthProvider(val js: firebase.auth.OAuthProvider, private val auth: FirebaseAuth) { actual constructor(provider: String, auth: FirebaseAuth) : this(firebase.auth.OAuthProvider(provider), auth) actual companion object { - actual fun credentialsWithAccessToken(providerId: String, accessToken: String): AuthCredential = getCredentials(providerId, accessToken = accessToken) - actual fun credentialsWithIDAndAccessToken(providerId: String, idToken: String, accessToken: String): AuthCredential = getCredentials(providerId, accessToken = accessToken, idToken = idToken) - actual fun credentialsWithIDRawNonceAndAccessToken(providerId: String, idToken: String, rawNonce: String, accessToken: String): AuthCredential = getCredentials(providerId, accessToken = accessToken, idToken = idToken, rawNonce = rawNonce) - actual fun credentialsWithIDAndRawNonce(providerId: String, idToken: String, rawNonce: String): AuthCredential = getCredentials(providerId, idToken = idToken, rawNonce = rawNonce) - - private fun getCredentials(provider: String, accessToken: String? = null, idToken: String? = null, rawNonce: String? = null): AuthCredential = rethrow { - val acT = accessToken - val idT = idToken - val rno = rawNonce - val provider = firebase.auth.OAuthProvider(provider) - val credentials = provider.credential(object : firebase.auth.OAuthCredentialOptions { - override val accessToken: String? = acT - override val idToken: String? = idT - override val rawNonce: String? = rno - }, accessToken) - return AuthCredential(credentials) + actual fun credential(providerId: String, accessToken: String?, idToken: String?, rawNonce: String?): OAuthCredential = rethrow { + firebase.auth.OAuthProvider(providerId) + .credential( + json( + "accessToken" to (accessToken ?: undefined), + "idToken" to (idToken ?: undefined), + "rawNonce" to (rawNonce ?: undefined) + ), + accessToken ?: undefined + ) + .let { OAuthCredential(it) } } } @@ -82,11 +80,11 @@ actual class PhoneAuthProvider(val js: firebase.auth.PhoneAuthProvider) { actual constructor(auth: FirebaseAuth) : this(firebase.auth.PhoneAuthProvider(auth.js)) - actual fun credentialWithVerificationIdAndSmsCode(verificationId: String, smsCode: String): PhoneAuthCredential = PhoneAuthCredential(firebase.auth.PhoneAuthProvider.credential(verificationId, smsCode)) + actual fun credential(verificationId: String, smsCode: String): PhoneAuthCredential = PhoneAuthCredential(firebase.auth.PhoneAuthProvider.credential(verificationId, smsCode)) actual suspend fun verifyPhoneNumber(phoneNumber: String, verificationProvider: PhoneVerificationProvider): AuthCredential = rethrow { val verificationId = js.verifyPhoneNumber(phoneNumber, verificationProvider.verifier).await() val verificationCode = verificationProvider.getVerificationCode(verificationId) - credentialWithVerificationIdAndSmsCode(verificationId, verificationCode) + credential(verificationId, verificationCode) } } @@ -96,5 +94,5 @@ actual interface PhoneVerificationProvider { } actual object TwitterAuthProvider { - actual fun credentialWithTokenAndSecret(token: String, secret: String): AuthCredential = AuthCredential(firebase.auth.TwitterAuthProvider.credential(token, secret)) + actual fun credential(token: String, secret: String): AuthCredential = AuthCredential(firebase.auth.TwitterAuthProvider.credential(token, secret)) } \ No newline at end of file diff --git a/firebase-auth/src/jsMain/kotlin/dev/gitlive/firebase/auth/user.kt b/firebase-auth/src/jsMain/kotlin/dev/gitlive/firebase/auth/user.kt index 580d15dd4..0a0463231 100644 --- a/firebase-auth/src/jsMain/kotlin/dev/gitlive/firebase/auth/user.kt +++ b/firebase-auth/src/jsMain/kotlin/dev/gitlive/firebase/auth/user.kt @@ -37,7 +37,7 @@ actual class FirebaseUser internal constructor(val js: firebase.user.User) { } actual suspend fun reauthenticateAndRetrieveData(credential: AuthCredential): AuthResult = rethrow { AuthResult(js.reauthenticateWithCredential(credential.js).await()) } - actual suspend fun sendEmailVerification(actionCodeSettings: ActionCodeSettings?) = rethrow { js.sendEmailVerification(actionCodeSettings?.js).await() } + actual suspend fun sendEmailVerification(actionCodeSettings: ActionCodeSettings?) = rethrow { js.sendEmailVerification(actionCodeSettings?.toJson()).await() } actual suspend fun unlink(provider: String): FirebaseUser? = rethrow { FirebaseUser(js.unlink(provider).await()) } actual suspend fun updateEmail(email: String) = rethrow { js.updateEmail(email).await() } actual suspend fun updatePassword(password: String) = rethrow { js.updatePassword(password).await() } @@ -49,7 +49,7 @@ actual class FirebaseUser internal constructor(val js: firebase.user.User) { } js.updateProfile(request).await() } - actual suspend fun verifyBeforeUpdateEmail(newEmail: String, actionCodeSettings: ActionCodeSettings?) = rethrow { js.verifyBeforeUpdateEmail(newEmail, actionCodeSettings?.js).await() } + actual suspend fun verifyBeforeUpdateEmail(newEmail: String, actionCodeSettings: ActionCodeSettings?) = rethrow { js.verifyBeforeUpdateEmail(newEmail, actionCodeSettings?.toJson()).await() } } actual class UserInfo(val js: firebase.user.UserInfo) { diff --git a/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals.kt b/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals.kt index 3ae30e9b6..d8c587411 100644 --- a/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals.kt +++ b/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals.kt @@ -63,8 +63,8 @@ external object firebase { fun confirmPasswordReset(code: String, newPassword: String): Promise fun createUserWithEmailAndPassword(email: String, password: String): Promise fun fetchSignInMethodsForEmail(email: String): Promise> - fun sendPasswordResetEmail(email: String, actionCodeSettings: ActionCodeSettings?): Promise - fun sendSignInLinkToEmail(email: String, actionCodeSettings: ActionCodeSettings?): Promise + fun sendPasswordResetEmail(email: String, actionCodeSettings: Any?): Promise + fun sendSignInLinkToEmail(email: String, actionCodeSettings: Any?): Promise fun signInWithEmailAndPassword(email: String, password: String): Promise fun signInWithCustomToken(token: String): Promise fun signInAnonymously(): Promise @@ -147,7 +147,7 @@ external object firebase { open class OAuthProvider(providerId: String) : AuthProvider { val providerId: String - fun credential(optionsOrIdToken: OAuthCredentialOptions?, accessToken: String?): AuthCredential + fun credential(optionsOrIdToken: Any?, accessToken: String?): AuthCredential fun addScope(scope: String) fun setCustomParameters(customOAuthParameters: Map) @@ -201,13 +201,13 @@ external object firebase { fun linkWithCredential(credential: auth.AuthCredential): Promise fun reauthenticateWithCredential(credential: auth.AuthCredential): Promise fun reload(): Promise - fun sendEmailVerification(actionCodeSettings: auth.ActionCodeSettings?): Promise + fun sendEmailVerification(actionCodeSettings: Any?): Promise fun unlink(providerId: String): Promise fun updateEmail(newEmail: String): Promise fun updatePassword(newPassword: String): Promise fun updatePhoneNumber(phoneCredential: auth.AuthCredential): Promise fun updateProfile(profile: ProfileUpdateRequest): Promise - fun verifyBeforeUpdateEmail(newEmail: String, actionCodeSettings: auth.ActionCodeSettings?): Promise + fun verifyBeforeUpdateEmail(newEmail: String, actionCodeSettings: Any?): Promise } abstract class UserMetadata { From 9e3be34ee71cbbf4822ac1e52e5b1291eea62e99 Mon Sep 17 00:00:00 2001 From: nbransby Date: Tue, 20 Oct 2020 22:25:48 +0100 Subject: [PATCH 30/32] remove awaitExpectedResult --- .../kotlin/dev/gitlive/firebase/auth/auth.kt | 6 +-- .../kotlin/dev/gitlive/firebase/auth/auth.kt | 50 ++++--------------- .../dev/gitlive/firebase/auth/credentials.kt | 4 +- .../dev/gitlive/firebase/auth/multifactor.kt | 4 +- .../kotlin/dev/gitlive/firebase/auth/user.kt | 8 +-- .../dev/gitlive/firebase/database/database.kt | 4 +- .../gitlive/firebase/functions/functions.kt | 4 +- 7 files changed, 26 insertions(+), 54 deletions(-) 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 c01a21dda..823ead25b 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 @@ -54,10 +54,10 @@ class FirebaseAuthTest { fun testFetchSignInMethods() = runTest { val email = "test+${Random.nextInt(100000)}@test.com" var signInMethodResult = Firebase.auth.fetchSignInMethodsForEmail(email) - assertEquals(emptyList(), signInMethodResult.signInMethods) + assertEquals(emptyList(), signInMethodResult) Firebase.auth.createUserWithEmailAndPassword(email, "test123") signInMethodResult = Firebase.auth.fetchSignInMethodsForEmail(email) - assertEquals(listOf("password"), signInMethodResult.signInMethods) + assertEquals(listOf("password"), signInMethodResult) Firebase.auth.signInWithEmailAndPassword(email, "test123").user!!.delete() } @@ -85,7 +85,7 @@ class FirebaseAuthTest { @Test fun testSignInWithCredential() = runTest { - val credential = EmailAuthProvider.credentialWithEmail("test@test.com", "test123") + val credential = EmailAuthProvider.credential("test@test.com", "test123") val result = Firebase.auth.signInWithCredential(credential) assertEquals("mn8kgIFnxLO7il8GpTa5g0ObP6I2", result.user!!.uid) 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 cd356f439..a752f83fd 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 @@ -45,9 +45,9 @@ actual class FirebaseAuth internal constructor(val ios: FIRAuth) { actual suspend fun confirmPasswordReset(code: String, newPassword: String) = ios.await { confirmPasswordResetWithCode(code, newPassword, it) }.run { Unit } actual suspend fun createUserWithEmailAndPassword(email: String, password: String) = - AuthResult(ios.awaitExpectedResult { createUserWithEmail(email = email, password = password, completion = it) }) + AuthResult(ios.awaitResult { createUserWithEmail(email = email, password = password, completion = it) }) - actual suspend fun fetchSignInMethodsForEmail(email: String) = ios.awaitResult { fetchSignInMethodsForEmail(email, it) }.orEmpty() + actual suspend fun fetchSignInMethodsForEmail(email: String) = ios.awaitResult { fetchSignInMethodsForEmail(email, it) } as List actual suspend fun sendPasswordResetEmail(email: String, actionCodeSettings: ActionCodeSettings?) { ios.await { actionCodeSettings?.let { actionSettings -> sendPasswordResetWithEmail(email, actionSettings.toIos(), it) } ?: sendPasswordResetWithEmail(email = email, completion = it) } @@ -56,24 +56,24 @@ actual class FirebaseAuth internal constructor(val ios: FIRAuth) { actual suspend fun sendSignInLinkToEmail(email: String, actionCodeSettings: ActionCodeSettings) = ios.await { sendSignInLinkToEmail(email, actionCodeSettings.toIos(), it) }.run { Unit } actual suspend fun signInWithEmailAndPassword(email: String, password: String) = - AuthResult(ios.awaitExpectedResult { signInWithEmail(email = email, password = password, completion = it) }) + AuthResult(ios.awaitResult { signInWithEmail(email = email, password = password, completion = it) }) actual suspend fun signInWithCustomToken(token: String) = - AuthResult(ios.awaitExpectedResult { signInWithCustomToken(token, it) }) + AuthResult(ios.awaitResult { signInWithCustomToken(token, it) }) actual suspend fun signInAnonymously() = - AuthResult(ios.awaitExpectedResult { signInAnonymouslyWithCompletion(it) }) + AuthResult(ios.awaitResult { signInAnonymouslyWithCompletion(it) }) actual suspend fun signInWithCredential(authCredential: AuthCredential) = - AuthResult(ios.awaitExpectedResult { signInWithCredential(authCredential.ios, it) }) + AuthResult(ios.awaitResult { signInWithCredential(authCredential.ios, it) }) actual suspend fun signOut() = ios.throwError { signOut(it) }.run { Unit } actual suspend fun updateCurrentUser(user: FirebaseUser) = ios.await { updateCurrentUser(user.ios, it) }.run { Unit } - actual suspend fun verifyPasswordResetCode(code: String): String = ios.awaitExpectedResult { verifyPasswordResetCode(code, it) } + actual suspend fun verifyPasswordResetCode(code: String): String = ios.awaitResult { verifyPasswordResetCode(code, it) } actual suspend fun checkActionCode(code: String): T { - val result = ios.awaitExpectedResult { checkActionCode(code, it) } + val result = ios.awaitResult { checkActionCode(code, it) } @Suppress("UNCHECKED_CAST") return when(result.operation) { FIRActionCodeOperationUnknown -> Error @@ -93,7 +93,7 @@ actual class AuthResult internal constructor(val ios: FIRAuthDataResult) { get() = FirebaseUser(ios.user) } -internal fun ActionCodeSettings.toIos() = FIRActionCodeSettings().let { +internal fun ActionCodeSettings.toIos() = FIRActionCodeSettings().also { it.URL = NSURL.URLWithString(url) androidPackageName?.run { it.setAndroidPackageName(androidPackageName, installIfNotAvailable, minimumVersion) } it.dynamicLinkDomain = dynamicLinkDomain @@ -127,41 +127,13 @@ internal fun T.throwError(block: T.(errorPointer: CPointer T.awaitResult(function: T.(callback: (R?, NSError?) -> Unit) -> Unit): R? { - val job = CompletableDeferred() - function { result, error -> - if(error != null) { - job.completeExceptionally(error.toException()) - } else { - job.complete(result) - } - } - return job.await() -} - -internal suspend fun T.awaitResult(default: R, function: T.(callback: (R?, NSError?) -> Unit) -> Unit): R { +internal suspend fun T.awaitResult(function: T.(callback: (R, NSError?) -> Unit) -> Unit): R { val job = CompletableDeferred() function { result, error -> - if(result != null) { + if(error == null) { job.complete(result) - } else if(error != null) { - job.completeExceptionally(error.toException()) } else { - job.complete(default) - } - } - return job.await() -} - -internal suspend fun T.awaitExpectedResult(function: T.(callback: (R?, NSError?) -> Unit) -> Unit): R { - val job = CompletableDeferred() - function { result, error -> - if(result != null) { - job.complete(result) - } else if(error != null) { job.completeExceptionally(error.toException()) - } else { - job.completeExceptionally(UnexpectedNullResultException()) } } return job.await() diff --git a/firebase-auth/src/iosMain/kotlin/dev/gitlive/firebase/auth/credentials.kt b/firebase-auth/src/iosMain/kotlin/dev/gitlive/firebase/auth/credentials.kt index 3045e6832..e73afb7d6 100644 --- a/firebase-auth/src/iosMain/kotlin/dev/gitlive/firebase/auth/credentials.kt +++ b/firebase-auth/src/iosMain/kotlin/dev/gitlive/firebase/auth/credentials.kt @@ -69,7 +69,7 @@ actual class OAuthProvider(val ios: FIROAuthProvider, private val auth: Firebase null}.toMap() } - actual suspend fun signIn(signInProvider: SignInProvider): AuthResult = AuthResult(ios.awaitExpectedResult { auth.ios.signInWithProvider(ios, signInProvider.delegate, it) }) + actual suspend fun signIn(signInProvider: SignInProvider): AuthResult = AuthResult(ios.awaitResult { auth.ios.signInWithProvider(ios, signInProvider.delegate, it) }) } actual class SignInProvider(val delegate: FIRAuthUIDelegateProtocol) @@ -80,7 +80,7 @@ actual class PhoneAuthProvider(val ios: FIRPhoneAuthProvider) { actual fun credential(verificationId: String, smsCode: String): PhoneAuthCredential = PhoneAuthCredential(ios.credentialWithVerificationID(verificationId, smsCode)) actual suspend fun verifyPhoneNumber(phoneNumber: String, verificationProvider: PhoneVerificationProvider): AuthCredential { - val verificationId: String = ios.awaitExpectedResult { ios.verifyPhoneNumber(phoneNumber, verificationProvider.delegate, it) } + val verificationId: String = ios.awaitResult { ios.verifyPhoneNumber(phoneNumber, verificationProvider.delegate, it) } val verificationCode = verificationProvider.getVerificationCode() return credential(verificationId, verificationCode) } diff --git a/firebase-auth/src/iosMain/kotlin/dev/gitlive/firebase/auth/multifactor.kt b/firebase-auth/src/iosMain/kotlin/dev/gitlive/firebase/auth/multifactor.kt index add3a8e98..2822e7406 100644 --- a/firebase-auth/src/iosMain/kotlin/dev/gitlive/firebase/auth/multifactor.kt +++ b/firebase-auth/src/iosMain/kotlin/dev/gitlive/firebase/auth/multifactor.kt @@ -10,7 +10,7 @@ actual class MultiFactor(val ios: FIRMultiFactor) { actual val enrolledFactors: List get() = ios.enrolledFactors.mapNotNull { info -> (info as? FIRMultiFactorInfo)?.let{ MultiFactorInfo(it) } } actual suspend fun enroll(multiFactorAssertion: MultiFactorAssertion, displayName: String?) = ios.await { enrollWithAssertion(multiFactorAssertion.ios, displayName, it) }.run { Unit } - actual suspend fun getSession(): MultiFactorSession = MultiFactorSession(ios.awaitExpectedResult { getSessionWithCompletion(completion = it) }) + actual suspend fun getSession(): MultiFactorSession = MultiFactorSession(ios.awaitResult { getSessionWithCompletion(completion = it) }) actual suspend fun unenroll(multiFactorInfo: MultiFactorInfo) = ios.await { unenrollWithInfo(multiFactorInfo.ios, it) }.run { Unit } actual suspend fun unenroll(factorUid: String) = ios.await { unenrollWithFactorUID(factorUid, it) }.run { Unit } } @@ -38,5 +38,5 @@ actual class MultiFactorResolver(val ios: FIRMultiFactorResolver) { actual val hints: List = ios.hints.mapNotNull { hint -> (hint as? FIRMultiFactorInfo)?.let { MultiFactorInfo(it) } } actual val session: MultiFactorSession = MultiFactorSession(ios.session) - actual suspend fun resolveSignIn(assertion: MultiFactorAssertion): AuthResult = AuthResult(ios.awaitExpectedResult { resolveSignInWithAssertion(assertion.ios, it) }) + actual suspend fun resolveSignIn(assertion: MultiFactorAssertion): AuthResult = AuthResult(ios.awaitResult { resolveSignInWithAssertion(assertion.ios, it) }) } \ No newline at end of file diff --git a/firebase-auth/src/iosMain/kotlin/dev/gitlive/firebase/auth/user.kt b/firebase-auth/src/iosMain/kotlin/dev/gitlive/firebase/auth/user.kt index 5a23e7909..e9cdacf4e 100644 --- a/firebase-auth/src/iosMain/kotlin/dev/gitlive/firebase/auth/user.kt +++ b/firebase-auth/src/iosMain/kotlin/dev/gitlive/firebase/auth/user.kt @@ -39,18 +39,18 @@ actual class FirebaseUser internal constructor(val ios: FIRUser) { ios.awaitResult { getIDTokenForcingRefresh(forceRefresh, it) } actual suspend fun linkWithCredential(credential: AuthCredential): AuthResult = - AuthResult(ios.awaitExpectedResult { linkWithCredential(credential.ios, it) }) + AuthResult(ios.awaitResult { linkWithCredential(credential.ios, it) }) actual suspend fun reauthenticate(credential: AuthCredential) = - ios.awaitExpectedResult { reauthenticateWithCredential(credential.ios, it) }.run { Unit } + ios.await { reauthenticateWithCredential(credential.ios, it) } actual suspend fun reauthenticateAndRetrieveData(credential: AuthCredential): AuthResult = - AuthResult(ios.awaitExpectedResult { reauthenticateAndRetrieveDataWithCredential(credential.ios, it) }) + AuthResult(ios.awaitResult { reauthenticateAndRetrieveDataWithCredential(credential.ios, it) }) actual suspend fun sendEmailVerification(actionCodeSettings: ActionCodeSettings?) = ios.await { actionCodeSettings?.let { settings -> sendEmailVerificationWithActionCodeSettings(settings.toIos(), it) } ?: sendEmailVerificationWithCompletion(it) - }.run { Unit } + } actual suspend fun unlink(provider: String): FirebaseUser? { val user: FIRUser? = ios.awaitResult { unlinkFromProvider(provider, it) } diff --git a/firebase-database/src/iosMain/kotlin/dev/gitlive/firebase/database/database.kt b/firebase-database/src/iosMain/kotlin/dev/gitlive/firebase/database/database.kt index a6a9c0fe7..2baacb2ec 100644 --- a/firebase-database/src/iosMain/kotlin/dev/gitlive/firebase/database/database.kt +++ b/firebase-database/src/iosMain/kotlin/dev/gitlive/firebase/database/database.kt @@ -175,9 +175,9 @@ actual class DatabaseException(message: String) : RuntimeException(message) private suspend fun T.awaitResult(whileOnline: Boolean, function: T.(callback: (NSError?, R?) -> Unit) -> Unit): R { val job = CompletableDeferred() function { error, result -> - if(result != null) { + if(error == null) { job.complete(result) - } else if(error != null) { + } else { job.completeExceptionally(DatabaseException(error.toString())) } } diff --git a/firebase-functions/src/iosMain/kotlin/dev/gitlive/firebase/functions/functions.kt b/firebase-functions/src/iosMain/kotlin/dev/gitlive/firebase/functions/functions.kt index bc129e00d..39d2b185d 100644 --- a/firebase-functions/src/iosMain/kotlin/dev/gitlive/firebase/functions/functions.kt +++ b/firebase-functions/src/iosMain/kotlin/dev/gitlive/firebase/functions/functions.kt @@ -70,9 +70,9 @@ private suspend fun T.await(function: T.(callback: (NSError?) -> Unit) -> Un suspend fun T.awaitResult(function: T.(callback: (R?, NSError?) -> Unit) -> Unit): R { val job = CompletableDeferred() function { result, error -> - if(result != null) { + if(error == null) { job.complete(result) - } else if(error != null) { + } else { job.completeExceptionally(FirebaseFunctionsException(error.toString())) } } From 74c13fce3c5ec4ad53f39a3aa91156c6b74e27c1 Mon Sep 17 00:00:00 2001 From: nbransby Date: Wed, 21 Oct 2020 18:03:35 +0100 Subject: [PATCH 31/32] finish ios auth fixes --- build.gradle.kts | 3 +-- .../kotlin/dev/gitlive/firebase/auth/auth.kt | 20 +++++++++---------- .../dev/gitlive/firebase/auth/credentials.kt | 4 ++-- .../kotlin/dev/gitlive/firebase/auth/user.kt | 4 ++-- .../dev/gitlive/firebase/database/database.kt | 8 ++++---- .../gitlive/firebase/firestore/firestore.kt | 12 +++++------ .../gitlive/firebase/functions/functions.kt | 8 ++++---- gradle.properties | 12 +++++------ 8 files changed, 34 insertions(+), 37 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 2ce3ddc38..fb36169db 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -56,8 +56,7 @@ subprojects { tasks.withType().configureEach { - onlyIf { !project.gradle.startParameter.taskNames.contains("publishToMavenLocal") - } + onlyIf { !project.gradle.startParameter.taskNames.contains("publishToMavenLocal") } } 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 a752f83fd..cca003b03 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 @@ -47,7 +47,9 @@ actual class FirebaseAuth internal constructor(val ios: FIRAuth) { actual suspend fun createUserWithEmailAndPassword(email: String, password: String) = AuthResult(ios.awaitResult { createUserWithEmail(email = email, password = password, completion = it) }) - actual suspend fun fetchSignInMethodsForEmail(email: String) = ios.awaitResult { fetchSignInMethodsForEmail(email, it) } as List + @Suppress("UNCHECKED_CAST") + actual suspend fun fetchSignInMethodsForEmail(email: String) = + ios.awaitResult?> { fetchSignInMethodsForEmail(email, it) }.orEmpty() as List actual suspend fun sendPasswordResetEmail(email: String, actionCodeSettings: ActionCodeSettings?) { ios.await { actionCodeSettings?.let { actionSettings -> sendPasswordResetWithEmail(email, actionSettings.toIos(), it) } ?: sendPasswordResetWithEmail(email = email, completion = it) } @@ -73,7 +75,7 @@ actual class FirebaseAuth internal constructor(val ios: FIRAuth) { actual suspend fun verifyPasswordResetCode(code: String): String = ios.awaitResult { verifyPasswordResetCode(code, it) } actual suspend fun checkActionCode(code: String): T { - val result = ios.awaitResult { checkActionCode(code, it) } + val result: FIRActionCodeInfo = ios.awaitResult { checkActionCode(code, it) } @Suppress("UNCHECKED_CAST") return when(result.operation) { FIRActionCodeOperationUnknown -> Error @@ -95,7 +97,7 @@ actual class AuthResult internal constructor(val ios: FIRAuthDataResult) { internal fun ActionCodeSettings.toIos() = FIRActionCodeSettings().also { it.URL = NSURL.URLWithString(url) - androidPackageName?.run { it.setAndroidPackageName(androidPackageName, installIfNotAvailable, minimumVersion) } + androidPackageName?.run { it.setAndroidPackageName(packageName, installIfNotAvailable, minimumVersion) } it.dynamicLinkDomain = dynamicLinkDomain it.handleCodeInApp = canHandleCodeInApp iOSBundleId?.run { it.setIOSBundleID(this) } @@ -111,10 +113,6 @@ actual open class FirebaseAuthRecentLoginRequiredException(message: String): Fir actual open class FirebaseAuthUserCollisionException(message: String): FirebaseAuthException(message) actual open class FirebaseAuthWebException(message: String): FirebaseAuthException(message) -class UnexpectedNullResultException : Exception() { - override val message: String? = "The API encountered an unexpected null result" -} - internal fun T.throwError(block: T.(errorPointer: CPointer>) -> R): R { memScoped { val errorPointer: CPointer> = alloc>().ptr @@ -127,8 +125,8 @@ internal fun T.throwError(block: T.(errorPointer: CPointer T.awaitResult(function: T.(callback: (R, NSError?) -> Unit) -> Unit): R { - val job = CompletableDeferred() +internal suspend inline fun T.awaitResult(function: T.(callback: (R?, NSError?) -> Unit) -> Unit): R { + val job = CompletableDeferred() function { result, error -> if(error == null) { job.complete(result) @@ -136,10 +134,10 @@ internal suspend fun T.awaitResult(function: T.(callback: (R, NSError?) - job.completeExceptionally(error.toException()) } } - return job.await() + return job.await() as R } -internal suspend fun T.await(function: T.(callback: (NSError?) -> Unit) -> Unit) { +internal suspend inline fun T.await(function: T.(callback: (NSError?) -> Unit) -> Unit) { val job = CompletableDeferred() function { error -> if(error == null) { diff --git a/firebase-auth/src/iosMain/kotlin/dev/gitlive/firebase/auth/credentials.kt b/firebase-auth/src/iosMain/kotlin/dev/gitlive/firebase/auth/credentials.kt index e73afb7d6..546ccf991 100644 --- a/firebase-auth/src/iosMain/kotlin/dev/gitlive/firebase/auth/credentials.kt +++ b/firebase-auth/src/iosMain/kotlin/dev/gitlive/firebase/auth/credentials.kt @@ -40,12 +40,12 @@ actual class OAuthProvider(val ios: FIROAuthProvider, private val auth: Firebase actual companion object { actual fun credential(providerId: String, accessToken: String?, idToken: String?, rawNonce: String?): OAuthCredential { val credential = when { - idToken == null -> FIROAuthProvider.credentialWithProviderID(providerId = providerId, accessToken = accessToken!!) + idToken == null -> FIROAuthProvider.credentialWithProviderID(providerID = providerId, accessToken = accessToken!!) accessToken == null -> FIROAuthProvider.credentialWithProviderID(providerID = providerId, IDToken = idToken, rawNonce = rawNonce!!) rawNonce == null -> FIROAuthProvider.credentialWithProviderID(providerID = providerId, IDToken = idToken, accessToken = accessToken) else -> FIROAuthProvider.credentialWithProviderID(providerID = providerId, IDToken = idToken, rawNonce = rawNonce, accessToken = accessToken) } - return OAuthCredential(credential as FIROAuthCredential) + return OAuthCredential(credential) } } diff --git a/firebase-auth/src/iosMain/kotlin/dev/gitlive/firebase/auth/user.kt b/firebase-auth/src/iosMain/kotlin/dev/gitlive/firebase/auth/user.kt index e9cdacf4e..f75678485 100644 --- a/firebase-auth/src/iosMain/kotlin/dev/gitlive/firebase/auth/user.kt +++ b/firebase-auth/src/iosMain/kotlin/dev/gitlive/firebase/auth/user.kt @@ -42,7 +42,7 @@ actual class FirebaseUser internal constructor(val ios: FIRUser) { AuthResult(ios.awaitResult { linkWithCredential(credential.ios, it) }) actual suspend fun reauthenticate(credential: AuthCredential) = - ios.await { reauthenticateWithCredential(credential.ios, it) } + ios.awaitResult { reauthenticateWithCredential(credential.ios, it) }.run { Unit } actual suspend fun reauthenticateAndRetrieveData(credential: AuthCredential): AuthResult = AuthResult(ios.awaitResult { reauthenticateAndRetrieveDataWithCredential(credential.ios, it) }) @@ -69,7 +69,7 @@ actual class FirebaseUser internal constructor(val ios: FIRUser) { ios.await { request.commitChangesWithCompletion(it) } } actual suspend fun verifyBeforeUpdateEmail(newEmail: String, actionCodeSettings: ActionCodeSettings?) = ios.await { - actionCodeSettings?.let { actionSettings -> sendEmailVerificationBeforeUpdatingEmail(newEmail, actionSettings.ios, it) } ?: sendEmailVerificationBeforeUpdatingEmail(newEmail, it) + actionCodeSettings?.let { actionSettings -> sendEmailVerificationBeforeUpdatingEmail(newEmail, actionSettings.toIos(), it) } ?: sendEmailVerificationBeforeUpdatingEmail(newEmail, it) }.run { Unit } } diff --git a/firebase-database/src/iosMain/kotlin/dev/gitlive/firebase/database/database.kt b/firebase-database/src/iosMain/kotlin/dev/gitlive/firebase/database/database.kt index 2baacb2ec..768226334 100644 --- a/firebase-database/src/iosMain/kotlin/dev/gitlive/firebase/database/database.kt +++ b/firebase-database/src/iosMain/kotlin/dev/gitlive/firebase/database/database.kt @@ -172,8 +172,8 @@ actual class OnDisconnect internal constructor( actual class DatabaseException(message: String) : RuntimeException(message) -private suspend fun T.awaitResult(whileOnline: Boolean, function: T.(callback: (NSError?, R?) -> Unit) -> Unit): R { - val job = CompletableDeferred() +private suspend inline fun T.awaitResult(whileOnline: Boolean, function: T.(callback: (NSError?, R?) -> Unit) -> Unit): R { + val job = CompletableDeferred() function { error, result -> if(error == null) { job.complete(result) @@ -181,10 +181,10 @@ private suspend fun T.awaitResult(whileOnline: Boolean, function: T.(call job.completeExceptionally(DatabaseException(error.toString())) } } - return job.run { if(whileOnline) awaitWhileOnline() else await() } + return job.run { if(whileOnline) awaitWhileOnline() else await() } as R } -suspend fun T.await(whileOnline: Boolean, function: T.(callback: (NSError?, FIRDatabaseReference?) -> Unit) -> Unit) { +private suspend inline fun T.await(whileOnline: Boolean, function: T.(callback: (NSError?, FIRDatabaseReference?) -> Unit) -> Unit) { val job = CompletableDeferred() function { error, _ -> if(error == null) { diff --git a/firebase-firestore/src/iosMain/kotlin/dev/gitlive/firebase/firestore/firestore.kt b/firebase-firestore/src/iosMain/kotlin/dev/gitlive/firebase/firestore/firestore.kt index ce80013fe..aa629ed28 100644 --- a/firebase-firestore/src/iosMain/kotlin/dev/gitlive/firebase/firestore/firestore.kt +++ b/firebase-firestore/src/iosMain/kotlin/dev/gitlive/firebase/firestore/firestore.kt @@ -334,19 +334,19 @@ private fun T.throwError(block: T.(errorPointer: CPointer awaitResult(function: (callback: (T?, NSError?) -> Unit) -> Unit): T { - val job = CompletableDeferred() +internal suspend inline fun awaitResult(function: (callback: (T?, NSError?) -> Unit) -> Unit): T { + val job = CompletableDeferred() function { result, error -> - if(result != null) { + if(error == null) { job.complete(result) - } else if(error != null) { + } else { job.completeExceptionally(error.toException()) } } - return job.await() + return job.await() as T } -suspend fun await(function: (callback: (NSError?) -> Unit) -> T): T { +internal suspend inline fun await(function: (callback: (NSError?) -> Unit) -> T): T { val job = CompletableDeferred() val result = function { error -> if(error == null) { diff --git a/firebase-functions/src/iosMain/kotlin/dev/gitlive/firebase/functions/functions.kt b/firebase-functions/src/iosMain/kotlin/dev/gitlive/firebase/functions/functions.kt index 39d2b185d..41e44ac54 100644 --- a/firebase-functions/src/iosMain/kotlin/dev/gitlive/firebase/functions/functions.kt +++ b/firebase-functions/src/iosMain/kotlin/dev/gitlive/firebase/functions/functions.kt @@ -55,7 +55,7 @@ actual class HttpsCallableResult constructor(val ios: FIRHTTPSCallableResult) { actual class FirebaseFunctionsException(message: String): FirebaseException(message) -private suspend fun T.await(function: T.(callback: (NSError?) -> Unit) -> Unit) { +private suspend inline fun T.await(function: T.(callback: (NSError?) -> Unit) -> Unit) { val job = CompletableDeferred() function { error -> if(error == null) { @@ -67,8 +67,8 @@ private suspend fun T.await(function: T.(callback: (NSError?) -> Unit) -> Un job.await() } -suspend fun T.awaitResult(function: T.(callback: (R?, NSError?) -> Unit) -> Unit): R { - val job = CompletableDeferred() +private suspend inline fun T.awaitResult(function: T.(callback: (R?, NSError?) -> Unit) -> Unit): R { + val job = CompletableDeferred() function { result, error -> if(error == null) { job.complete(result) @@ -76,5 +76,5 @@ suspend fun T.awaitResult(function: T.(callback: (R?, NSError?) -> Unit) job.completeExceptionally(FirebaseFunctionsException(error.toString())) } } - return job.await() + return job.await() as R } \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index e4dba01e3..52744b5e9 100644 --- a/gradle.properties +++ b/gradle.properties @@ -6,9 +6,9 @@ android.useAndroidX=true testOptions.unitTests.isIncludeAndroidResources = true # Versions: -firebase-app.version=0.3.1 -firebase-auth.version=0.3.1 -firebase-common.version=0.3.1 -firebase-database.version=0.3.1 -firebase-firestore.version=0.3.1 -firebase-functions.version=0.3.1 +firebase-app.version=0.4.0 +firebase-auth.version=0.4.0 +firebase-common.version=0.4.0 +firebase-database.version=0.4.0 +firebase-firestore.version=0.4.0 +firebase-functions.version=0.4.0 From 57e3fe58ed3da63edd21a099ab627349c37e78c1 Mon Sep 17 00:00:00 2001 From: Nicholas Bransby-Williams Date: Wed, 21 Oct 2020 20:06:53 +0100 Subject: [PATCH 32/32] Update README.md --- README.md | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 83ae86865..4472f08f6 100644 --- a/README.md +++ b/README.md @@ -13,12 +13,12 @@ The following libraries are available for the various Firebase products. | Service or Product | Gradle Dependency | API Coverage | | ------------------------------------------------------------------------------------ | :-----------------------------------------------------------------------------------------------------------------------------------|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| [Authentication](https://firebase.google.com/docs/auth#kotlin-android) | [`dev.gitlive:firebase-auth:0.2.0`](https://search.maven.org/artifact/dev.gitlive/firebase-auth/0.2.0/pom) | [![40%](https://img.shields.io/badge/-50%25-red?style=flat-square)](/firebase-auth/src/commonMain/kotlin/dev/gitlive/firebase/auth/auth.kt) | -| [Realtime Database](https://firebase.google.com/docs/database#kotlin-android) | [`dev.gitlive:firebase-database:0.2.0`](https://search.maven.org/artifact/dev.gitlive/firebase-database/0.2.0/pom) | [![70%](https://img.shields.io/badge/-70%25-orange?style=flat-square)](/firebase-database/src/commonMain/kotlin/dev/gitlive/firebase/database/database.kt) | -| [Cloud Firestore](https://firebase.google.com/docs/firestore#kotlin-android) | [`dev.gitlive:firebase-firestore:0.2.0`](https://search.maven.org/artifact/dev.gitlive/firebase-firestore/0.2.0/pom) | [![60%](https://img.shields.io/badge/-60%25-orange?style=flat-square)](/firebase-firestore/src/commonMain/kotlin/dev/gitlive/firebase/firestore/firestore.kt) | -| [Cloud Functions](https://firebase.google.com/docs/functions/callable#kotlin-android)| [`dev.gitlive:firebase-functions:0.2.0`](https://search.maven.org/artifact/dev.gitlive/firebase-functions/0.2.0/pom) | [![80%](https://img.shields.io/badge/-80%25-green?style=flat-square)](/firebase-functions/src/commonMain/kotlin/dev/gitlive/firebase/functions/functions.kt) | -| [Cloud Messaging](https://firebase.google.com/docs/messaging#kotlin-android) | [`dev.gitlive:firebase-messaging:0.2.0`](https://search.maven.org/artifact/dev.gitlive/firebase-messaging/0.2.0/pom) | ![0%](https://img.shields.io/badge/-0%25-lightgrey?style=flat-square) | -| [Cloud Storage](https://firebase.google.com/docs/storage#kotlin-android) | [`dev.gitlive:firebase-storage:0.2.0`](https://search.maven.org/artifact/dev.gitlive/firebase-storage/0.2.0/pom) | ![0%](https://img.shields.io/badge/-0%25-lightgrey?style=flat-square) | +| [Authentication](https://firebase.google.com/docs/auth#kotlin-android) | [`dev.gitlive:firebase-auth:0.4.0`](https://search.maven.org/artifact/dev.gitlive/firebase-auth/0.4.0/pom) | [![80%](https://img.shields.io/badge/-80%25-green?style=flat-square)](/firebase-auth/src/commonMain/kotlin/dev/gitlive/firebase/auth/auth.kt) | +| [Realtime Database](https://firebase.google.com/docs/database#kotlin-android) | [`dev.gitlive:firebase-database:0.4.0`](https://search.maven.org/artifact/dev.gitlive/firebase-database/0.4.0/pom) | [![70%](https://img.shields.io/badge/-70%25-orange?style=flat-square)](/firebase-database/src/commonMain/kotlin/dev/gitlive/firebase/database/database.kt) | +| [Cloud Firestore](https://firebase.google.com/docs/firestore#kotlin-android) | [`dev.gitlive:firebase-firestore:0.4.0`](https://search.maven.org/artifact/dev.gitlive/firebase-firestore/0.4.0/pom) | [![60%](https://img.shields.io/badge/-60%25-orange?style=flat-square)](/firebase-firestore/src/commonMain/kotlin/dev/gitlive/firebase/firestore/firestore.kt) | +| [Cloud Functions](https://firebase.google.com/docs/functions/callable#kotlin-android)| [`dev.gitlive:firebase-functions:0.4.0`](https://search.maven.org/artifact/dev.gitlive/firebase-functions/0.4.0/pom) | [![80%](https://img.shields.io/badge/-80%25-green?style=flat-square)](/firebase-functions/src/commonMain/kotlin/dev/gitlive/firebase/functions/functions.kt) | +| [Cloud Messaging](https://firebase.google.com/docs/messaging#kotlin-android) | [`dev.gitlive:firebase-messaging:0.4.0`](https://search.maven.org/artifact/dev.gitlive/firebase-messaging/0.4.0/pom) | ![0%](https://img.shields.io/badge/-0%25-lightgrey?style=flat-square) | +| [Cloud Storage](https://firebase.google.com/docs/storage#kotlin-android) | [`dev.gitlive:firebase-storage:0.4.0`](https://search.maven.org/artifact/dev.gitlive/firebase-storage/0.4.0/pom) | ![0%](https://img.shields.io/badge/-0%25-lightgrey?style=flat-square) | Is the Firebase library or API you need missing? [Create an issue](https://github.com/GitLiveApp/firebase-kotlin-sdk/issues/new?labels=API+coverage&template=increase-api-coverage.md&title=Add+%5Bclass+name%5D.%5Bfunction+name%5D+to+%5Blibrary+name%5D+for+%5Bplatform+names%5D) to request additional API coverage or be awesome and [submit a PR](https://github.com/GitLiveApp/firebase-kotlin-sdk/fork) @@ -138,12 +138,12 @@ If you are building a Kotlin multiplatform library which will be consumed from J ```json "dependencies": { - "@gitlive/firebase-auth": "0.2.0", - "@gitlive/firebase-database": "0.2.0", - "@gitlive/firebase-firestore": "0.2.0", - "@gitlive/firebase-functions": "0.2.0", - "@gitlive/firebase-storage": "0.2.0", - "@gitlive/firebase-messaging": "0.2.0" + "@gitlive/firebase-auth": "0.4.0", + "@gitlive/firebase-database": "0.4.0", + "@gitlive/firebase-firestore": "0.4.0", + "@gitlive/firebase-functions": "0.4.0", + "@gitlive/firebase-storage": "0.4.0", + "@gitlive/firebase-messaging": "0.4.0" } ```