Skip to content

Commit

Permalink
Merge branch 'master' into coroutine_cancellation_fix
Browse files Browse the repository at this point in the history
  • Loading branch information
nbransby committed Oct 21, 2020
2 parents 9b237c2 + e9d38a5 commit beeab75
Show file tree
Hide file tree
Showing 22 changed files with 237 additions and 447 deletions.
2 changes: 0 additions & 2 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,6 @@ jobs:
arguments: :updateVersions
- 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)"
- name: Install Carthage
run: brew install carthage
- name: Publish
Expand Down
2 changes: 0 additions & 2 deletions .github/workflows/pull_request.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,6 @@ jobs:
java-version: 1.8
- 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)"
- name: Install Carthage
run: brew install carthage
- name: Assemble
Expand Down
24 changes: 12 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down Expand Up @@ -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"
}
```

Expand Down
3 changes: 1 addition & 2 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,7 @@ subprojects {


tasks.withType<Sign>().configureEach {
onlyIf { !project.gradle.startParameter.taskNames.contains("publishToMavenLocal")
}
onlyIf { !project.gradle.startParameter.taskNames.contains("publishToMavenLocal") }
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -44,19 +45,18 @@ 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<String> = android.fetchSignInMethodsForEmail(email).await().signInMethods.orEmpty()

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())
Expand All @@ -73,75 +73,42 @@ 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 <T : ActionCodeResult> 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) {
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(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<out T> {

actual abstract fun dataForResult(result: ActionCodeResult): T

actual object Email : ActionCodeDataType<String>() {
override fun dataForResult(result: ActionCodeResult): String = result.android.info!!.email
}
actual object PreviousEmail : ActionCodeDataType<String>() {
override fun dataForResult(result: ActionCodeResult): String = (result.android.info as ActionCodeEmailInfo).previousEmail
}
actual object MultiFactor : ActionCodeDataType<MultiFactorInfo?>() {
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<String>
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
}
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) } }
.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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -45,24 +46,12 @@ actual class OAuthProvider(val android: com.google.firebase.auth.OAuthProvider.B
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)
}
}
}.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)
}
}

Expand Down Expand Up @@ -99,9 +88,7 @@ actual class PhoneAuthProvider(val android: com.google.firebase.auth.PhoneAuthPr
launch {
val code = verificationProvider.getVerificationCode()
try {
val credentials =
credential(verificationId, code)
response.complete(Result.success(credentials))
response.complete(Result.success(credential(verificationId, code)))
} catch (e: Exception) {
response.complete(Result.failure(e))
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 }
Expand All @@ -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) {
Expand Down

0 comments on commit beeab75

Please sign in to comment.