Skip to content

Commit e9d38a5

Browse files
nbransbyavdyushinDaeda88Reedyuk
authored
Increase auth coverage (#92)
* Update FirebaseCore.def * Adding missing Auth calls * Add iOS implementation * Add providers * Trying to resolve Firestore issues * Added iOS methods * Add Javascript * Cleaned up .def files Dependencies now part of actual submodules * Add Test * Fixed compile for tests * Add missing firetore frameworks * Account for nullable results * Use Carthage instead of zip for linking. This cleans up dependencies and reduces build time * Track firestore version * Update yaml * Remove useless podspec * Code cleanup * Fixing remarks * Move ActionData into operator * fix test * Revert passing a Sealed class to credentials. This is a partial revert of commit dcbe856 * make ActionCodeSettings a data class * Revert "fix test" This reverts commit 8ba54ae * simplify fetchSignInMethodsForEmail by removing SignInMethodQueryResult simplify checkActionCode by removing Operation & ActionCodeDataType * Added fix to script. * Adjusted script * Added check of homebrew. * Removed brew install due to being already installed on github machines. * rename all credentialWithX functions to just credential use single credential function in OAuthProvider with optional params * remove awaitExpectedResult * finish ios auth fixes * Update README.md Co-authored-by: Grigory Avdyushin <[email protected]> Co-authored-by: Gijs van Veen <[email protected]> Co-authored-by: Andrew Reed <[email protected]>
1 parent 5844b72 commit e9d38a5

File tree

22 files changed

+237
-447
lines changed

22 files changed

+237
-447
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

README.md

+12-12
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,12 @@ The following libraries are available for the various Firebase products.
1313

1414
| Service or Product | Gradle Dependency | API Coverage |
1515
| ------------------------------------------------------------------------------------ | :-----------------------------------------------------------------------------------------------------------------------------------|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
16-
| [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) |
17-
| [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) |
18-
| [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) |
19-
| [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) |
20-
| [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) |
21-
| [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) |
16+
| [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) |
17+
| [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) |
18+
| [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) |
19+
| [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) |
20+
| [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) |
21+
| [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) |
2222

2323
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)
2424

@@ -138,12 +138,12 @@ If you are building a Kotlin multiplatform library which will be consumed from J
138138

139139
```json
140140
"dependencies": {
141-
"@gitlive/firebase-auth": "0.2.0",
142-
"@gitlive/firebase-database": "0.2.0",
143-
"@gitlive/firebase-firestore": "0.2.0",
144-
"@gitlive/firebase-functions": "0.2.0",
145-
"@gitlive/firebase-storage": "0.2.0",
146-
"@gitlive/firebase-messaging": "0.2.0"
141+
"@gitlive/firebase-auth": "0.4.0",
142+
"@gitlive/firebase-database": "0.4.0",
143+
"@gitlive/firebase-firestore": "0.4.0",
144+
"@gitlive/firebase-functions": "0.4.0",
145+
"@gitlive/firebase-storage": "0.4.0",
146+
"@gitlive/firebase-messaging": "0.4.0"
147147
}
148148
```
149149

build.gradle.kts

+1-2
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,7 @@ subprojects {
5656

5757

5858
tasks.withType<Sign>().configureEach {
59-
onlyIf { !project.gradle.startParameter.taskNames.contains("publishToMavenLocal")
60-
}
59+
onlyIf { !project.gradle.startParameter.taskNames.contains("publishToMavenLocal") }
6160
}
6261

6362

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

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

88
import com.google.firebase.auth.ActionCodeEmailInfo
99
import com.google.firebase.auth.ActionCodeMultiFactorInfo
10+
import com.google.firebase.auth.ActionCodeResult.*
1011
import com.google.firebase.auth.FirebaseAuth.AuthStateListener
1112
import dev.gitlive.firebase.Firebase
1213
import dev.gitlive.firebase.FirebaseApp
@@ -43,19 +44,18 @@ actual class FirebaseAuth internal constructor(val android: com.google.firebase.
4344
set(value) { android.setLanguageCode(value) }
4445

4546
actual suspend fun applyActionCode(code: String) = android.applyActionCode(code).await().run { Unit }
46-
actual suspend fun checkActionCode(code: String): ActionCodeResult = ActionCodeResult(android.checkActionCode(code).await())
4747
actual suspend fun confirmPasswordReset(code: String, newPassword: String) = android.confirmPasswordReset(code, newPassword).await().run { Unit }
4848

4949
actual suspend fun createUserWithEmailAndPassword(email: String, password: String) =
5050
AuthResult(android.createUserWithEmailAndPassword(email, password).await())
5151

52-
actual suspend fun fetchSignInMethodsForEmail(email: String): SignInMethodQueryResult = SignInMethodQueryResult(android.fetchSignInMethodsForEmail(email).await())
52+
actual suspend fun fetchSignInMethodsForEmail(email: String): List<String> = android.fetchSignInMethodsForEmail(email).await().signInMethods.orEmpty()
5353

5454
actual suspend fun sendPasswordResetEmail(email: String, actionCodeSettings: ActionCodeSettings?) {
55-
android.sendPasswordResetEmail(email, actionCodeSettings?.android).await()
55+
android.sendPasswordResetEmail(email, actionCodeSettings?.toAndroid()).await()
5656
}
5757

58-
actual suspend fun sendSignInLinkToEmail(email: String, actionCodeSettings: ActionCodeSettings) = android.sendSignInLinkToEmail(email, actionCodeSettings.android).await().run { Unit }
58+
actual suspend fun sendSignInLinkToEmail(email: String, actionCodeSettings: ActionCodeSettings) = android.sendSignInLinkToEmail(email, actionCodeSettings.toAndroid()).await().run { Unit }
5959

6060
actual suspend fun signInWithEmailAndPassword(email: String, password: String) =
6161
AuthResult(android.signInWithEmailAndPassword(email, password).await())
@@ -72,75 +72,42 @@ actual class FirebaseAuth internal constructor(val android: com.google.firebase.
7272

7373
actual suspend fun updateCurrentUser(user: FirebaseUser) = android.updateCurrentUser(user.android).await().run { Unit }
7474
actual suspend fun verifyPasswordResetCode(code: String): String = android.verifyPasswordResetCode(code).await()
75+
76+
actual suspend fun <T : ActionCodeResult> checkActionCode(code: String): T {
77+
val result = android.checkActionCode(code).await()
78+
@Suppress("UNCHECKED_CAST")
79+
return when(result.operation) {
80+
ERROR -> ActionCodeResult.Error
81+
SIGN_IN_WITH_EMAIL_LINK -> ActionCodeResult.SignInWithEmailLink
82+
VERIFY_EMAIL -> ActionCodeResult.VerifyEmail(result.info!!.email)
83+
PASSWORD_RESET -> ActionCodeResult.PasswordReset(result.info!!.email)
84+
RECOVER_EMAIL -> (result.info as ActionCodeEmailInfo).run {
85+
ActionCodeResult.RecoverEmail(email, previousEmail)
86+
}
87+
VERIFY_BEFORE_CHANGE_EMAIL -> (result.info as ActionCodeEmailInfo).run {
88+
ActionCodeResult.VerifyBeforeChangeEmail(email, previousEmail)
89+
}
90+
REVERT_SECOND_FACTOR_ADDITION -> (result.info as ActionCodeMultiFactorInfo).run {
91+
ActionCodeResult.RevertSecondFactorAddition(email, MultiFactorInfo(multiFactorInfo))
92+
}
93+
else -> throw UnsupportedOperationException(result.operation.toString())
94+
} as T
95+
}
96+
7597
}
7698

7799
actual class AuthResult internal constructor(val android: com.google.firebase.auth.AuthResult) {
78100
actual val user: FirebaseUser?
79101
get() = android.user?.let { FirebaseUser(it) }
80102
}
81103

82-
actual class ActionCodeResult(val android: com.google.firebase.auth.ActionCodeResult) {
83-
actual val operation: Operation
84-
get() = when (android.operation) {
85-
com.google.firebase.auth.ActionCodeResult.PASSWORD_RESET -> Operation.PasswordReset(this)
86-
com.google.firebase.auth.ActionCodeResult.VERIFY_EMAIL -> Operation.VerifyEmail(this)
87-
com.google.firebase.auth.ActionCodeResult.RECOVER_EMAIL -> Operation.RecoverEmail(this)
88-
com.google.firebase.auth.ActionCodeResult.ERROR -> Operation.Error
89-
com.google.firebase.auth.ActionCodeResult.SIGN_IN_WITH_EMAIL_LINK -> Operation.SignInWithEmailLink
90-
com.google.firebase.auth.ActionCodeResult.VERIFY_BEFORE_CHANGE_EMAIL -> Operation.VerifyBeforeChangeEmail(this)
91-
com.google.firebase.auth.ActionCodeResult.REVERT_SECOND_FACTOR_ADDITION -> Operation.RevertSecondFactorAddition(this)
92-
else -> Operation.Error
93-
}
94-
}
95-
96-
internal actual sealed class ActionCodeDataType<out T> {
97-
98-
actual abstract fun dataForResult(result: ActionCodeResult): T
99-
100-
actual object Email : ActionCodeDataType<String>() {
101-
override fun dataForResult(result: ActionCodeResult): String = result.android.info!!.email
102-
}
103-
actual object PreviousEmail : ActionCodeDataType<String>() {
104-
override fun dataForResult(result: ActionCodeResult): String = (result.android.info as ActionCodeEmailInfo).previousEmail
105-
}
106-
actual object MultiFactor : ActionCodeDataType<MultiFactorInfo?>() {
107-
override fun dataForResult(result: ActionCodeResult): MultiFactorInfo? = (result.android.info as? ActionCodeMultiFactorInfo)?.multiFactorInfo?.let { MultiFactorInfo(it) }
108-
}
109-
}
110-
111-
actual class SignInMethodQueryResult(val android: com.google.firebase.auth.SignInMethodQueryResult) {
112-
actual val signInMethods: List<String>
113-
get() = android.signInMethods ?: emptyList()
114-
}
115-
116-
actual class ActionCodeSettings private constructor(val android: com.google.firebase.auth.ActionCodeSettings) {
117-
118-
actual constructor(url: String,
119-
androidPackageName: AndroidPackageName?,
120-
dynamicLinkDomain: String?,
121-
canHandleCodeInApp: Boolean,
122-
iOSBundleId: String?
123-
) : this(com.google.firebase.auth.ActionCodeSettings.newBuilder().apply {
124-
this.url = url
125-
androidPackageName?.let {
126-
this.setAndroidPackageName(it.androidPackageName, it.installIfNotAvailable, it.minimumVersion)
127-
}
128-
this.dynamicLinkDomain = dynamicLinkDomain
129-
this.handleCodeInApp = canHandleCodeInApp
130-
this.iosBundleId = iosBundleId
131-
}.build())
132-
133-
actual val canHandleCodeInApp: Boolean
134-
get() = android.canHandleCodeInApp()
135-
actual val androidPackageName: AndroidPackageName?
136-
get() = android.androidPackageName?.let {
137-
AndroidPackageName(it, android.androidInstallApp, android.androidMinimumVersion)
138-
}
139-
actual val iOSBundle: String?
140-
get() = android.iosBundle
141-
actual val url: String
142-
get() = android.url
143-
}
104+
internal fun ActionCodeSettings.toAndroid() = com.google.firebase.auth.ActionCodeSettings.newBuilder()
105+
.setUrl(url)
106+
.also { androidPackageName?.run { it.setAndroidPackageName(packageName, installIfNotAvailable, minimumVersion) } }
107+
.also { dynamicLinkDomain?.run { it.setDynamicLinkDomain(this) } }
108+
.setHandleCodeInApp(canHandleCodeInApp)
109+
.also { iOSBundleId?.run { it.setIOSBundleId(this) } }
110+
.build()
144111

145112
actual typealias FirebaseAuthException = com.google.firebase.auth.FirebaseAuthException
146113
actual typealias FirebaseAuthActionCodeException = com.google.firebase.auth.FirebaseAuthActionCodeException

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

+8-21
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
@@ -45,24 +46,12 @@ actual class OAuthProvider(val android: com.google.firebase.auth.OAuthProvider.B
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 credentials(type: OAuthCredentialsType): AuthCredential {
49-
val credential = com.google.firebase.auth.OAuthProvider.newCredentialBuilder(type.providerId).apply {
50-
when (type) {
51-
is OAuthCredentialsType.AccessToken -> accessToken = type.accessToken
52-
is OAuthCredentialsType.IdAndAccessToken -> {
53-
accessToken = type.accessToken
54-
setIdToken(type.idToken)
55-
}
56-
is OAuthCredentialsType.IdAndAccessTokenAndRawNonce -> {
57-
accessToken = type.accessToken
58-
setIdTokenWithRawNonce(type.idToken, type.rawNonce)
59-
}
60-
is OAuthCredentialsType.IdTokenAndRawNonce -> {
61-
setIdTokenWithRawNonce(type.idToken, type.rawNonce)
62-
}
63-
}
64-
}.build()
65-
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)
6655
}
6756
}
6857

@@ -99,9 +88,7 @@ actual class PhoneAuthProvider(val android: com.google.firebase.auth.PhoneAuthPr
9988
launch {
10089
val code = verificationProvider.getVerificationCode()
10190
try {
102-
val credentials =
103-
credential(verificationId, code)
104-
response.complete(Result.success(credentials))
91+
response.complete(Result.success(credential(verificationId, code)))
10592
} catch (e: Exception) {
10693
response.complete(Result.failure(e))
10794
}

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) {

0 commit comments

Comments
 (0)