Skip to content

Commit 295b2a7

Browse files
committed
simplify fetchSignInMethodsForEmail by removing SignInMethodQueryResult
simplify checkActionCode by removing Operation & ActionCodeDataType
1 parent 151571d commit 295b2a7

File tree

4 files changed

+79
-159
lines changed
  • firebase-auth/src
    • androidMain/kotlin/dev/gitlive/firebase/auth
    • commonMain/kotlin/dev/gitlive/firebase/auth
    • iosMain/kotlin/dev/gitlive/firebase/auth
    • jsMain/kotlin/dev/gitlive/firebase/auth

4 files changed

+79
-159
lines changed

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

+24-36
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,13 +44,12 @@ 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?) {
5555
android.sendPasswordResetEmail(email, actionCodeSettings?.toAndroid()).await()
@@ -72,47 +72,35 @@ 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-
116104
private fun ActionCodeSettings.toAndroid() = com.google.firebase.auth.ActionCodeSettings.newBuilder()
117105
.setUrl(url)
118106
.also { androidPackageName?.run { it.setAndroidPackageName(packageName, installIfNotAvailable, minimumVersion) } }

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

+10-44
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,10 @@ expect class FirebaseAuth {
2121
val idTokenChanged: Flow<FirebaseUser?>
2222
var languageCode: String
2323
suspend fun applyActionCode(code: String)
24-
suspend fun checkActionCode(code: String): ActionCodeResult
24+
suspend fun <T: ActionCodeResult> checkActionCode(code: String): T
2525
suspend fun confirmPasswordReset(code: String, newPassword: String)
2626
suspend fun createUserWithEmailAndPassword(email: String, password: String): AuthResult
27-
suspend fun fetchSignInMethodsForEmail(email: String): SignInMethodQueryResult
27+
suspend fun fetchSignInMethodsForEmail(email: String): List<String>
2828
suspend fun sendPasswordResetEmail(email: String, actionCodeSettings: ActionCodeSettings? = null)
2929
suspend fun sendSignInLinkToEmail(email: String, actionCodeSettings: ActionCodeSettings)
3030
suspend fun signInWithEmailAndPassword(email: String, password: String): AuthResult
@@ -40,48 +40,14 @@ expect class AuthResult {
4040
val user: FirebaseUser?
4141
}
4242

43-
expect class ActionCodeResult {
44-
val operation: Operation
45-
}
46-
47-
fun <T, A: ActionCodeDataType<T>> ActionCodeResult.getData(type: A): T? {
48-
return type.dataForResult(this)
49-
}
50-
51-
expect class SignInMethodQueryResult {
52-
val signInMethods: List<String>
53-
}
54-
55-
sealed class Operation {
56-
class PasswordReset(result: ActionCodeResult) : Operation() {
57-
val email: String = ActionCodeDataType.Email.dataForResult(result)
58-
}
59-
class VerifyEmail(result: ActionCodeResult) : Operation() {
60-
val email: String = ActionCodeDataType.Email.dataForResult(result)
61-
}
62-
class RecoverEmail(result: ActionCodeResult) : Operation() {
63-
val email: String = ActionCodeDataType.Email.dataForResult(result)
64-
val previousEmail: String = ActionCodeDataType.PreviousEmail.dataForResult(result)
65-
}
66-
object Error : Operation()
67-
object SignInWithEmailLink : Operation()
68-
class VerifyBeforeChangeEmail(result: ActionCodeResult) : Operation() {
69-
val email: String = ActionCodeDataType.Email.dataForResult(result)
70-
val previousEmail: String = ActionCodeDataType.PreviousEmail.dataForResult(result)
71-
}
72-
class RevertSecondFactorAddition(result: ActionCodeResult) : Operation() {
73-
val email: String = ActionCodeDataType.Email.dataForResult(result)
74-
val multiFactorInfo: MultiFactorInfo? = ActionCodeDataType.MultiFactor.dataForResult(result)
75-
}
76-
}
77-
78-
internal expect sealed class ActionCodeDataType<out T> {
79-
80-
abstract fun dataForResult(result: ActionCodeResult): T
81-
82-
object Email : ActionCodeDataType<String>
83-
object PreviousEmail : ActionCodeDataType<String>
84-
object MultiFactor : ActionCodeDataType<MultiFactorInfo?>
43+
sealed class ActionCodeResult {
44+
object Error : ActionCodeResult()
45+
object SignInWithEmailLink : ActionCodeResult()
46+
class PasswordReset internal constructor(val email: String) : ActionCodeResult()
47+
class VerifyEmail internal constructor(val email: String) : ActionCodeResult()
48+
class RecoverEmail internal constructor(val email: String, val previousEmail: String) : ActionCodeResult()
49+
class VerifyBeforeChangeEmail internal constructor(val email: String, val previousEmail: String) : ActionCodeResult()
50+
class RevertSecondFactorAddition internal constructor(val email: String, val multiFactorInfo: MultiFactorInfo?) : ActionCodeResult()
8551
}
8652

8753
data class ActionCodeSettings(

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

+17-36
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import cocoapods.FirebaseAuth.*
88
import dev.gitlive.firebase.Firebase
99
import dev.gitlive.firebase.FirebaseApp
1010
import dev.gitlive.firebase.FirebaseException
11+
import dev.gitlive.firebase.auth.ActionCodeResult.*
1112
import kotlinx.cinterop.*
1213
import kotlinx.coroutines.CompletableDeferred
1314
import kotlinx.coroutines.channels.awaitClose
@@ -41,16 +42,12 @@ actual class FirebaseAuth internal constructor(val ios: FIRAuth) {
4142
set(value) { ios.setLanguageCode(value) }
4243

4344
actual suspend fun applyActionCode(code: String) = ios.await { applyActionCode(code, it) }.run { Unit }
44-
actual suspend fun checkActionCode(code: String): ActionCodeResult = ActionCodeResult(ios.awaitExpectedResult { checkActionCode(code, it) })
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) =
4848
AuthResult(ios.awaitExpectedResult { createUserWithEmail(email = email, password = password, completion = it) })
4949

50-
actual suspend fun fetchSignInMethodsForEmail(email: String): SignInMethodQueryResult {
51-
val signInMethods: List<*>? = ios.awaitResult { fetchSignInMethodsForEmail(email, it) }
52-
return SignInMethodQueryResult(signInMethods?.mapNotNull { it as String } ?: emptyList())
53-
}
50+
actual suspend fun fetchSignInMethodsForEmail(email: String) = ios.awaitResult { fetchSignInMethodsForEmail(email, it) }.orEmpty()
5451

5552
actual suspend fun sendPasswordResetEmail(email: String, actionCodeSettings: ActionCodeSettings?) {
5653
ios.await { actionCodeSettings?.let { actionSettings -> sendPasswordResetWithEmail(email, actionSettings.toIos(), it) } ?: sendPasswordResetWithEmail(email = email, completion = it) }
@@ -74,44 +71,28 @@ actual class FirebaseAuth internal constructor(val ios: FIRAuth) {
7471

7572
actual suspend fun updateCurrentUser(user: FirebaseUser) = ios.await { updateCurrentUser(user.ios, it) }.run { Unit }
7673
actual suspend fun verifyPasswordResetCode(code: String): String = ios.awaitExpectedResult { verifyPasswordResetCode(code, it) }
74+
75+
actual suspend fun <T : ActionCodeResult> checkActionCode(code: String): T {
76+
val result = ios.awaitExpectedResult { checkActionCode(code, it) }
77+
@Suppress("UNCHECKED_CAST")
78+
return when(result.operation) {
79+
FIRActionCodeOperationUnknown -> Error
80+
FIRActionCodeOperationEmailLink -> SignInWithEmailLink
81+
FIRActionCodeOperationVerifyEmail -> VerifyEmail(result.email!!)
82+
FIRActionCodeOperationPasswordReset -> PasswordReset(result.email!!)
83+
FIRActionCodeOperationRecoverEmail -> RecoverEmail(result.email!!, result.previousEmail!!)
84+
FIRActionCodeOperationVerifyAndChangeEmail -> VerifyBeforeChangeEmail(result.email!!, result.previousEmail!!)
85+
FIRActionCodeOperationRevertSecondFactorAddition -> RevertSecondFactorAddition(result.email!!, null)
86+
else -> throw UnsupportedOperationException(result.operation.toString())
87+
} as T
88+
}
7789
}
7890

7991
actual class AuthResult internal constructor(val ios: FIRAuthDataResult) {
8092
actual val user: FirebaseUser?
8193
get() = FirebaseUser(ios.user)
8294
}
8395

84-
actual class ActionCodeResult(val ios: FIRActionCodeInfo) {
85-
actual val operation: Operation
86-
get() = when (ios.operation) {
87-
FIRActionCodeOperationPasswordReset -> Operation.PasswordReset(this)
88-
FIRActionCodeOperationVerifyEmail -> Operation.VerifyEmail(this)
89-
FIRActionCodeOperationRecoverEmail -> Operation.RecoverEmail(this)
90-
FIRActionCodeOperationUnknown-> Operation.Error
91-
FIRActionCodeOperationEmailLink -> Operation.SignInWithEmailLink
92-
FIRActionCodeOperationVerifyAndChangeEmail -> Operation.VerifyBeforeChangeEmail(this)
93-
FIRActionCodeOperationRevertSecondFactorAddition -> Operation.RevertSecondFactorAddition(this)
94-
else -> Operation.Error
95-
}
96-
}
97-
98-
internal actual sealed class ActionCodeDataType<out T> {
99-
100-
actual abstract fun dataForResult(result: ActionCodeResult): T
101-
102-
actual object Email : ActionCodeDataType<String>() {
103-
override fun dataForResult(result: ActionCodeResult): String = result.ios.email!!
104-
}
105-
actual object PreviousEmail : ActionCodeDataType<String>() {
106-
override fun dataForResult(result: ActionCodeResult): String = result.ios.previousEmail!!
107-
}
108-
actual object MultiFactor : ActionCodeDataType<MultiFactorInfo?>() {
109-
override fun dataForResult(result: ActionCodeResult): MultiFactorInfo? = null
110-
}
111-
}
112-
113-
actual class SignInMethodQueryResult(actual val signInMethods: List<String>)
114-
11596
private fun ActionCodeSettings.toIos() = FIRActionCodeSettings().let {
11697
it.URL = NSURL.URLWithString(url)
11798
androidPackageName?.run { it.setAndroidPackageName(androidPackageName, installIfNotAvailable, minimumVersion) }

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

+28-43
Original file line numberDiff line numberDiff line change
@@ -38,13 +38,12 @@ actual class FirebaseAuth internal constructor(val js: firebase.auth.Auth) {
3838
set(value) { js.languageCode = value }
3939

4040
actual suspend fun applyActionCode(code: String) = rethrow { js.applyActionCode(code).await() }
41-
actual suspend fun checkActionCode(code: String): ActionCodeResult = rethrow { ActionCodeResult(js.checkActionCode(code).await()) }
4241
actual suspend fun confirmPasswordReset(code: String, newPassword: String) = rethrow { js.confirmPasswordReset(code, newPassword).await() }
4342

4443
actual suspend fun createUserWithEmailAndPassword(email: String, password: String) =
4544
rethrow { AuthResult(js.createUserWithEmailAndPassword(email, password).await()) }
4645

47-
actual suspend fun fetchSignInMethodsForEmail(email: String): SignInMethodQueryResult = rethrow { SignInMethodQueryResult(js.fetchSignInMethodsForEmail(email).await().asList()) }
46+
actual suspend fun fetchSignInMethodsForEmail(email: String): List<String> = rethrow { js.fetchSignInMethodsForEmail(email).await().asList() }
4847

4948
actual suspend fun sendPasswordResetEmail(email: String, actionCodeSettings: ActionCodeSettings?) =
5049
rethrow { js.sendPasswordResetEmail(email, actionCodeSettings?.toJson()).await() }
@@ -55,63 +54,49 @@ actual class FirebaseAuth internal constructor(val js: firebase.auth.Auth) {
5554
actual suspend fun signInWithEmailAndPassword(email: String, password: String) =
5655
rethrow { AuthResult(js.signInWithEmailAndPassword(email, password).await()) }
5756

58-
actual suspend fun signInWithCustomToken(token: String)
59-
= rethrow { AuthResult(js.signInWithCustomToken(token).await()) }
57+
actual suspend fun signInWithCustomToken(token: String) =
58+
rethrow { AuthResult(js.signInWithCustomToken(token).await()) }
6059

61-
actual suspend fun signInAnonymously()
62-
= rethrow { AuthResult(js.signInAnonymously().await()) }
60+
actual suspend fun signInAnonymously() =
61+
rethrow { AuthResult(js.signInAnonymously().await()) }
6362

6463
actual suspend fun signInWithCredential(authCredential: AuthCredential) =
6564
rethrow { AuthResult(js.signInWithCredential(authCredential.js).await()) }
6665

6766
actual suspend fun signOut() = rethrow { js.signOut().await() }
6867

6968
actual suspend fun updateCurrentUser(user: FirebaseUser) =
70-
rethrow {
71-
js.updateCurrentUser(user.js).await()
72-
}
73-
actual suspend fun verifyPasswordResetCode(code: String): String =
74-
rethrow {
75-
js.verifyPasswordResetCode(code).await()
76-
}
69+
rethrow { js.updateCurrentUser(user.js).await() }
7770

71+
actual suspend fun verifyPasswordResetCode(code: String): String =
72+
rethrow { js.verifyPasswordResetCode(code).await() }
73+
74+
actual suspend fun <T : ActionCodeResult> checkActionCode(code: String): T = rethrow {
75+
val result = js.checkActionCode(code).await()
76+
@Suppress("UNCHECKED_CAST")
77+
return when(result.operation) {
78+
"EMAIL_SIGNIN" -> ActionCodeResult.SignInWithEmailLink
79+
"VERIFY_EMAIL" -> ActionCodeResult.VerifyEmail(result.data.email!!)
80+
"PASSWORD_RESET" -> ActionCodeResult.PasswordReset(result.data.email!!)
81+
"RECOVER_EMAIL" -> ActionCodeResult.RecoverEmail(result.data.email!!, result.data.previousEmail!!)
82+
"VERIFY_AND_CHANGE_EMAIL" -> ActionCodeResult.VerifyBeforeChangeEmail(
83+
result.data.email!!,
84+
result.data.previousEmail!!
85+
)
86+
"REVERT_SECOND_FACTOR_ADDITION" -> ActionCodeResult.RevertSecondFactorAddition(
87+
result.data.email!!,
88+
result.data.multiFactorInfo?.let { MultiFactorInfo(it) }
89+
)
90+
else -> throw UnsupportedOperationException(result.operation)
91+
} as T
92+
}
7893
}
7994

8095
actual class AuthResult internal constructor(val js: firebase.auth.AuthResult) {
8196
actual val user: FirebaseUser?
8297
get() = rethrow { js.user?.let { FirebaseUser(it) } }
8398
}
8499

85-
actual class ActionCodeResult(val js: firebase.auth.ActionCodeInfo) {
86-
actual val operation: Operation
87-
get() = when (js.operation) {
88-
"PASSWORD_RESET" -> Operation.PasswordReset(this)
89-
"VERIFY_EMAIL" -> Operation.VerifyEmail(this)
90-
"RECOVER_EMAIL" -> Operation.RecoverEmail(this)
91-
"EMAIL_SIGNIN" -> Operation.SignInWithEmailLink
92-
"VERIFY_AND_CHANGE_EMAIL" -> Operation.VerifyBeforeChangeEmail(this)
93-
"REVERT_SECOND_FACTOR_ADDITION" -> Operation.RevertSecondFactorAddition(this)
94-
else -> Operation.Error
95-
}
96-
}
97-
98-
internal actual sealed class ActionCodeDataType<out T> {
99-
100-
actual abstract fun dataForResult(result: ActionCodeResult): T
101-
102-
actual object Email : ActionCodeDataType<String>() {
103-
override fun dataForResult(result: ActionCodeResult): String = result.js.data.email!!
104-
}
105-
actual object PreviousEmail : ActionCodeDataType<String>() {
106-
override fun dataForResult(result: ActionCodeResult): String = result.js.data.previousEmail!!
107-
}
108-
actual object MultiFactor : ActionCodeDataType<MultiFactorInfo?>() {
109-
override fun dataForResult(result: ActionCodeResult): MultiFactorInfo? = result.js.data.multiFactorInfo?.let { MultiFactorInfo(it) }
110-
}
111-
}
112-
113-
actual class SignInMethodQueryResult(actual val signInMethods: List<String>)
114-
115100
private fun ActionCodeSettings.toJson() = json(
116101
"android" to (androidPackageName?.run { json("installApp" to installIfNotAvailable, "minimumVersion" to minimumVersion, "packageName" to packageName) } ?: undefined),
117102
"dynamicLinkDomain" to (dynamicLinkDomain ?: undefined),

0 commit comments

Comments
 (0)