Skip to content

Commit f117c3d

Browse files
committed
Merge remote-tracking branch 'GitLiveApp/increase_auth_coverage' into coroutine_cancellation_fix
2 parents 92edca0 + 9e3be34 commit f117c3d

File tree

17 files changed

+117
-151
lines changed

17 files changed

+117
-151
lines changed

.github/workflows/publish.yml

-2
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,6 @@ jobs:
2424
arguments: :updateVersions
2525
- name: Grant execute permission for gradlew
2626
run: chmod +x gradlew
27-
- name: Install Homebrew
28-
run: ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
2927
- name: Install Carthage
3028
run: brew install carthage
3129
- name: Publish

.github/workflows/pull_request.yml

-2
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,6 @@ jobs:
2020
java-version: 1.8
2121
- name: Grant execute permission for gradlew
2222
run: chmod +x gradlew
23-
- name: Install Homebrew
24-
run: ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
2523
- name: Install Carthage
2624
run: brew install carthage
2725
- name: Assemble

firebase-auth/src/androidMain/kotlin/dev/gitlive/firebase/auth/auth.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ actual class AuthResult internal constructor(val android: com.google.firebase.au
101101
get() = android.user?.let { FirebaseUser(it) }
102102
}
103103

104-
private fun ActionCodeSettings.toAndroid() = com.google.firebase.auth.ActionCodeSettings.newBuilder()
104+
internal fun ActionCodeSettings.toAndroid() = com.google.firebase.auth.ActionCodeSettings.newBuilder()
105105
.setUrl(url)
106106
.also { androidPackageName?.run { it.setAndroidPackageName(packageName, installIfNotAvailable, minimumVersion) } }
107107
.also { dynamicLinkDomain?.run { it.setDynamicLinkDomain(this) } }

firebase-auth/src/androidMain/kotlin/dev/gitlive/firebase/auth/credentials.kt

+14-29
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ package dev.gitlive.firebase.auth
66

77
import android.app.Activity
88
import com.google.firebase.FirebaseException
9+
import com.google.firebase.auth.OAuthProvider
910
import com.google.firebase.auth.PhoneAuthProvider
1011
import kotlinx.coroutines.CompletableDeferred
1112
import kotlinx.coroutines.coroutineScope
@@ -23,48 +24,34 @@ actual class PhoneAuthCredential(override val android: com.google.firebase.auth.
2324
actual class OAuthCredential(override val android: com.google.firebase.auth.OAuthCredential) : AuthCredential(android)
2425

2526
actual object EmailAuthProvider {
26-
actual fun credentialWithEmail(
27+
actual fun credential(
2728
email: String,
2829
password: String
2930
): AuthCredential = AuthCredential(com.google.firebase.auth.EmailAuthProvider.getCredential(email, password))
3031
}
3132

3233
actual object FacebookAuthProvider {
33-
actual fun credentialWithAccessToken(accessToken: String): AuthCredential = AuthCredential(com.google.firebase.auth.FacebookAuthProvider.getCredential(accessToken))
34+
actual fun credential(accessToken: String): AuthCredential = AuthCredential(com.google.firebase.auth.FacebookAuthProvider.getCredential(accessToken))
3435
}
3536

3637
actual object GithubAuthProvider {
37-
actual fun credentialWithToken(token: String): AuthCredential = AuthCredential(com.google.firebase.auth.GithubAuthProvider.getCredential(token))
38+
actual fun credential(token: String): AuthCredential = AuthCredential(com.google.firebase.auth.GithubAuthProvider.getCredential(token))
3839
}
3940

4041
actual object GoogleAuthProvider {
41-
actual fun credentialWithIDAndAccessToken(idToken: String, accessToken: String): AuthCredential = AuthCredential(com.google.firebase.auth.GoogleAuthProvider.getCredential(idToken, accessToken))
42+
actual fun credential(idToken: String, accessToken: String): AuthCredential = AuthCredential(com.google.firebase.auth.GoogleAuthProvider.getCredential(idToken, accessToken))
4243
}
4344

4445
actual class OAuthProvider(val android: com.google.firebase.auth.OAuthProvider.Builder, private val auth: FirebaseAuth) {
4546
actual constructor(provider: String, auth: FirebaseAuth) : this(com.google.firebase.auth.OAuthProvider.newBuilder(provider, auth.android), auth)
4647

4748
actual companion object {
48-
actual fun credentialsWithAccessToken(providerId: String, accessToken: String): AuthCredential = createCredentials(providerId) {
49-
this.accessToken = accessToken
50-
}
51-
actual fun credentialsWithIDAndAccessToken(providerId: String, idToken: String, accessToken: String): AuthCredential = createCredentials(providerId) {
52-
setIdToken(idToken)
53-
this.accessToken = accessToken
54-
}
55-
actual fun credentialsWithIDRawNonceAndAccessToken(providerId: String, idToken: String, rawNonce: String, accessToken: String): AuthCredential = createCredentials(providerId) {
56-
setIdTokenWithRawNonce(idToken, rawNonce)
57-
this.accessToken = accessToken
58-
}
59-
actual fun credentialsWithIDAndRawNonce(providerId: String, idToken: String, rawNonce: String): AuthCredential = createCredentials(providerId) {
60-
setIdTokenWithRawNonce(idToken, rawNonce)
61-
}
62-
63-
private fun createCredentials(providerId: String, block: com.google.firebase.auth.OAuthProvider.CredentialBuilder.() -> Unit): AuthCredential {
64-
val credential = com.google.firebase.auth.OAuthProvider.newCredentialBuilder(providerId).apply {
65-
block()
66-
}.build()
67-
return (credential as? com.google.firebase.auth.OAuthCredential)?.let { OAuthCredential(it) } ?: AuthCredential(credential)
49+
actual fun credential(providerId: String, accessToken: String?, idToken: String?, rawNonce: String?): OAuthCredential {
50+
val builder = OAuthProvider.newCredentialBuilder(providerId)
51+
accessToken?.let { builder.accessToken = it }
52+
idToken?.let { builder.idToken = it }
53+
rawNonce?.let { builder.setIdTokenWithRawNonce(idToken!!, it) }
54+
return OAuthCredential(builder.build() as com.google.firebase.auth.OAuthCredential)
6855
}
6956
}
7057

@@ -87,7 +74,7 @@ actual class PhoneAuthProvider(val android: com.google.firebase.auth.PhoneAuthPr
8774

8875
actual constructor(auth: FirebaseAuth) : this(com.google.firebase.auth.PhoneAuthProvider.getInstance(auth.android))
8976

90-
actual fun credentialWithVerificationIdAndSmsCode(verificationId: String, smsCode: String): PhoneAuthCredential = PhoneAuthCredential(com.google.firebase.auth.PhoneAuthProvider.getCredential(verificationId, smsCode))
77+
actual fun credential(verificationId: String, smsCode: String): PhoneAuthCredential = PhoneAuthCredential(com.google.firebase.auth.PhoneAuthProvider.getCredential(verificationId, smsCode))
9178
actual suspend fun verifyPhoneNumber(phoneNumber: String, verificationProvider: PhoneVerificationProvider): AuthCredential = coroutineScope {
9279
val response = CompletableDeferred<Result<AuthCredential>>()
9380
val callback = object :
@@ -101,9 +88,7 @@ actual class PhoneAuthProvider(val android: com.google.firebase.auth.PhoneAuthPr
10188
launch {
10289
val code = verificationProvider.getVerificationCode()
10390
try {
104-
val credentials =
105-
credentialWithVerificationIdAndSmsCode(verificationId, code)
106-
response.complete(Result.success(credentials))
91+
response.complete(Result.success(credential(verificationId, code)))
10792
} catch (e: Exception) {
10893
response.complete(Result.failure(e))
10994
}
@@ -134,5 +119,5 @@ actual interface PhoneVerificationProvider {
134119
}
135120

136121
actual object TwitterAuthProvider {
137-
actual fun credentialWithTokenAndSecret(token: String, secret: String): AuthCredential = AuthCredential(com.google.firebase.auth.TwitterAuthProvider.getCredential(token, secret))
122+
actual fun credential(token: String, secret: String): AuthCredential = AuthCredential(com.google.firebase.auth.TwitterAuthProvider.getCredential(token, secret))
138123
}

firebase-auth/src/androidMain/kotlin/dev/gitlive/firebase/auth/user.kt

+4-3
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,8 @@ actual class FirebaseUser internal constructor(val android: com.google.firebase.
3838
actual suspend fun reauthenticate(credential: AuthCredential) = android.reauthenticate(credential.android).await().run { Unit }
3939
actual suspend fun reauthenticateAndRetrieveData(credential: AuthCredential): AuthResult = AuthResult(android.reauthenticateAndRetrieveData(credential.android).await())
4040
actual suspend fun sendEmailVerification(actionCodeSettings: ActionCodeSettings?) {
41-
val request = actionCodeSettings?.android?.let { android.sendEmailVerification(it) } ?: android.sendEmailVerification()
42-
request.await().run { Unit }
41+
val request = actionCodeSettings?.let { android.sendEmailVerification(it.toAndroid()) } ?: android.sendEmailVerification()
42+
request.await()
4343
}
4444
actual suspend fun unlink(provider: String): FirebaseUser? = android.unlink(provider).await().user?.let { FirebaseUser(it) }
4545
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.
5252
}.build()
5353
android.updateProfile(request).await()
5454
}
55-
actual suspend fun verifyBeforeUpdateEmail(newEmail: String, actionCodeSettings: ActionCodeSettings?) = android.verifyBeforeUpdateEmail(newEmail, actionCodeSettings?.android).await().run { Unit }
55+
actual suspend fun verifyBeforeUpdateEmail(newEmail: String, actionCodeSettings: ActionCodeSettings?) =
56+
android.verifyBeforeUpdateEmail(newEmail, actionCodeSettings?.toAndroid()).await().run { Unit }
5657
}
5758

5859
actual class UserInfo(val android: com.google.firebase.auth.UserInfo) {

firebase-auth/src/commonMain/kotlin/dev/gitlive/firebase/auth/credentials.kt

+7-11
Original file line numberDiff line numberDiff line change
@@ -14,27 +14,24 @@ expect class PhoneAuthCredential : AuthCredential
1414
expect class OAuthCredential : AuthCredential
1515

1616
expect object EmailAuthProvider {
17-
fun credentialWithEmail(email: String, password: String): AuthCredential
17+
fun credential(email: String, password: String): AuthCredential
1818
}
1919

2020
expect object FacebookAuthProvider {
21-
fun credentialWithAccessToken(accessToken: String): AuthCredential
21+
fun credential(accessToken: String): AuthCredential
2222
}
2323

2424
expect object GithubAuthProvider {
25-
fun credentialWithToken(token: String): AuthCredential
25+
fun credential(token: String): AuthCredential
2626
}
2727

2828
expect object GoogleAuthProvider {
29-
fun credentialWithIDAndAccessToken(idToken: String, accessToken: String): AuthCredential
29+
fun credential(idToken: String, accessToken: String): AuthCredential
3030
}
3131

3232
expect class OAuthProvider constructor(provider: String, auth: FirebaseAuth = Firebase.auth) {
3333
companion object {
34-
fun credentialsWithAccessToken(providerId: String, accessToken: String): AuthCredential
35-
fun credentialsWithIDAndAccessToken(providerId: String, idToken: String, accessToken: String): AuthCredential
36-
fun credentialsWithIDRawNonceAndAccessToken(providerId: String, idToken: String, rawNonce: String, accessToken: String): AuthCredential
37-
fun credentialsWithIDAndRawNonce(providerId: String, idToken: String, rawNonce: String): AuthCredential
34+
fun credential(providerId: String, accessToken: String? = null, idToken: String? = null, rawNonce: String? = null): OAuthCredential
3835
}
3936

4037
fun addScope(vararg scope: String)
@@ -46,13 +43,12 @@ expect class OAuthProvider constructor(provider: String, auth: FirebaseAuth = Fi
4643
expect class SignInProvider
4744

4845
expect class PhoneAuthProvider constructor(auth: FirebaseAuth = Firebase.auth) {
49-
fun credentialWithVerificationIdAndSmsCode(verificationId: String, smsCode: String): PhoneAuthCredential
46+
fun credential(verificationId: String, smsCode: String): PhoneAuthCredential
5047
suspend fun verifyPhoneNumber(phoneNumber: String, verificationProvider: PhoneVerificationProvider): AuthCredential
51-
5248
}
5349

5450
expect interface PhoneVerificationProvider
5551

5652
expect object TwitterAuthProvider {
57-
fun credentialWithTokenAndSecret(token: String, secret: String): AuthCredential
53+
fun credential(token: String, secret: String): AuthCredential
5854
}

firebase-auth/src/commonTest/kotlin/dev/gitlive/firebase/auth/auth.kt

+3-3
Original file line numberDiff line numberDiff line change
@@ -54,10 +54,10 @@ class FirebaseAuthTest {
5454
fun testFetchSignInMethods() = runTest {
5555
val email = "test+${Random.nextInt(100000)}@test.com"
5656
var signInMethodResult = Firebase.auth.fetchSignInMethodsForEmail(email)
57-
assertEquals(emptyList(), signInMethodResult.signInMethods)
57+
assertEquals(emptyList(), signInMethodResult)
5858
Firebase.auth.createUserWithEmailAndPassword(email, "test123")
5959
signInMethodResult = Firebase.auth.fetchSignInMethodsForEmail(email)
60-
assertEquals(listOf("password"), signInMethodResult.signInMethods)
60+
assertEquals(listOf("password"), signInMethodResult)
6161

6262
Firebase.auth.signInWithEmailAndPassword(email, "test123").user!!.delete()
6363
}
@@ -85,7 +85,7 @@ class FirebaseAuthTest {
8585

8686
@Test
8787
fun testSignInWithCredential() = runTest {
88-
val credential = EmailAuthProvider.credentialWithEmail("[email protected]", "test123")
88+
val credential = EmailAuthProvider.credential("[email protected]", "test123")
8989
val result = Firebase.auth.signInWithCredential(credential)
9090
assertEquals("mn8kgIFnxLO7il8GpTa5g0ObP6I2", result.user!!.uid)
9191

firebase-auth/src/iosMain/kotlin/dev/gitlive/firebase/auth/auth.kt

+11-39
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,9 @@ actual class FirebaseAuth internal constructor(val ios: FIRAuth) {
4545
actual suspend fun confirmPasswordReset(code: String, newPassword: String) = ios.await { confirmPasswordResetWithCode(code, newPassword, it) }.run { Unit }
4646

4747
actual suspend fun createUserWithEmailAndPassword(email: String, password: String) =
48-
AuthResult(ios.awaitExpectedResult { createUserWithEmail(email = email, password = password, completion = it) })
48+
AuthResult(ios.awaitResult { createUserWithEmail(email = email, password = password, completion = it) })
4949

50-
actual suspend fun fetchSignInMethodsForEmail(email: String) = ios.awaitResult { fetchSignInMethodsForEmail(email, it) }.orEmpty()
50+
actual suspend fun fetchSignInMethodsForEmail(email: String) = ios.awaitResult { fetchSignInMethodsForEmail(email, it) } as List<String>
5151

5252
actual suspend fun sendPasswordResetEmail(email: String, actionCodeSettings: ActionCodeSettings?) {
5353
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) {
5656
actual suspend fun sendSignInLinkToEmail(email: String, actionCodeSettings: ActionCodeSettings) = ios.await { sendSignInLinkToEmail(email, actionCodeSettings.toIos(), it) }.run { Unit }
5757

5858
actual suspend fun signInWithEmailAndPassword(email: String, password: String) =
59-
AuthResult(ios.awaitExpectedResult { signInWithEmail(email = email, password = password, completion = it) })
59+
AuthResult(ios.awaitResult { signInWithEmail(email = email, password = password, completion = it) })
6060

6161
actual suspend fun signInWithCustomToken(token: String) =
62-
AuthResult(ios.awaitExpectedResult { signInWithCustomToken(token, it) })
62+
AuthResult(ios.awaitResult { signInWithCustomToken(token, it) })
6363

6464
actual suspend fun signInAnonymously() =
65-
AuthResult(ios.awaitExpectedResult { signInAnonymouslyWithCompletion(it) })
65+
AuthResult(ios.awaitResult { signInAnonymouslyWithCompletion(it) })
6666

6767
actual suspend fun signInWithCredential(authCredential: AuthCredential) =
68-
AuthResult(ios.awaitExpectedResult { signInWithCredential(authCredential.ios, it) })
68+
AuthResult(ios.awaitResult { signInWithCredential(authCredential.ios, it) })
6969

7070
actual suspend fun signOut() = ios.throwError { signOut(it) }.run { Unit }
7171

7272
actual suspend fun updateCurrentUser(user: FirebaseUser) = ios.await { updateCurrentUser(user.ios, it) }.run { Unit }
73-
actual suspend fun verifyPasswordResetCode(code: String): String = ios.awaitExpectedResult { verifyPasswordResetCode(code, it) }
73+
actual suspend fun verifyPasswordResetCode(code: String): String = ios.awaitResult { verifyPasswordResetCode(code, it) }
7474

7575
actual suspend fun <T : ActionCodeResult> checkActionCode(code: String): T {
76-
val result = ios.awaitExpectedResult { checkActionCode(code, it) }
76+
val result = ios.awaitResult { checkActionCode(code, it) }
7777
@Suppress("UNCHECKED_CAST")
7878
return when(result.operation) {
7979
FIRActionCodeOperationUnknown -> Error
@@ -93,7 +93,7 @@ actual class AuthResult internal constructor(val ios: FIRAuthDataResult) {
9393
get() = FirebaseUser(ios.user)
9494
}
9595

96-
private fun ActionCodeSettings.toIos() = FIRActionCodeSettings().let {
96+
internal fun ActionCodeSettings.toIos() = FIRActionCodeSettings().also {
9797
it.URL = NSURL.URLWithString(url)
9898
androidPackageName?.run { it.setAndroidPackageName(androidPackageName, installIfNotAvailable, minimumVersion) }
9999
it.dynamicLinkDomain = dynamicLinkDomain
@@ -127,41 +127,13 @@ internal fun <T, R> T.throwError(block: T.(errorPointer: CPointer<ObjCObjectVar<
127127
}
128128
}
129129

130-
internal suspend fun <T, R> T.awaitResult(function: T.(callback: (R?, NSError?) -> Unit) -> Unit): R? {
131-
val job = CompletableDeferred<R?>()
132-
function { result, error ->
133-
if(error != null) {
134-
job.completeExceptionally(error.toException())
135-
} else {
136-
job.complete(result)
137-
}
138-
}
139-
return job.await()
140-
}
141-
142-
internal suspend fun <T, R> T.awaitResult(default: R, function: T.(callback: (R?, NSError?) -> Unit) -> Unit): R {
130+
internal suspend fun <T, R> T.awaitResult(function: T.(callback: (R, NSError?) -> Unit) -> Unit): R {
143131
val job = CompletableDeferred<R>()
144132
function { result, error ->
145-
if(result != null) {
133+
if(error == null) {
146134
job.complete(result)
147-
} else if(error != null) {
148-
job.completeExceptionally(error.toException())
149135
} else {
150-
job.complete(default)
151-
}
152-
}
153-
return job.await()
154-
}
155-
156-
internal suspend fun <T, R> T.awaitExpectedResult(function: T.(callback: (R?, NSError?) -> Unit) -> Unit): R {
157-
val job = CompletableDeferred<R>()
158-
function { result, error ->
159-
if(result != null) {
160-
job.complete(result)
161-
} else if(error != null) {
162136
job.completeExceptionally(error.toException())
163-
} else {
164-
job.completeExceptionally(UnexpectedNullResultException())
165137
}
166138
}
167139
return job.await()

0 commit comments

Comments
 (0)