1
1
package dev.teamhub.firebase.auth
2
2
3
+ import cocoapods.FirebaseAuth.*
3
4
import dev.teamhub.firebase.Firebase
4
5
import dev.teamhub.firebase.FirebaseApp
5
6
import dev.teamhub.firebase.FirebaseException
7
+ import kotlinx.cinterop.*
8
+ import kotlinx.coroutines.channels.awaitClose
9
+ import kotlinx.coroutines.flow.*
10
+ import platform.Foundation.*
11
+ import kotlinx.coroutines.CompletableDeferred
6
12
7
- actual val Firebase .auth: FirebaseAuth
8
- get() = kotlin.TODO (" not implemented" ) // To change initializer of created properties use File | Settings | File Templates.
9
13
10
- actual fun Firebase.auth (app : FirebaseApp ): FirebaseAuth {
11
- kotlin.TODO (" not implemented" ) // To change body of created functions use File | Settings | File Templates.
12
- }
14
+ actual val Firebase .auth
15
+ get() = FirebaseAuth (FIRAuth .auth())
16
+
17
+ actual fun Firebase.auth (app : FirebaseApp ) =
18
+ FirebaseAuth (FIRAuth .authWithApp(app.ios))
19
+
20
+ actual class FirebaseAuth internal constructor(val ios : FIRAuth ) {
13
21
14
- actual class FirebaseAuth {
15
22
actual val currentUser: FirebaseUser ?
16
- get() = TODO (" not implemented" ) // To change initializer of created properties use File | Settings | File Templates.
17
- actual val authStateChanged: kotlinx.coroutines.flow.Flow <FirebaseUser ?>
18
- get() = TODO (" not implemented" ) // To change initializer of created properties use File | Settings | File Templates.
23
+ get() = ios.currentUser?.let { FirebaseUser (it) }
19
24
20
- actual suspend fun signInWithCustomToken (token : String ): AuthResult {
21
- TODO (" not implemented" ) // To change body of created functions use File | Settings | File Templates.
22
- }
25
+ actual suspend fun signInWithCustomToken (token : String ) =
26
+ AuthResult (ios.awaitResult { signInWithCustomToken(token, it) })
23
27
24
- actual suspend fun signInAnonymously (): AuthResult {
25
- TODO (" not implemented" ) // To change body of created functions use File | Settings | File Templates.
26
- }
28
+ actual suspend fun signInAnonymously () =
29
+ AuthResult (ios.awaitResult { signInAnonymouslyWithCompletion(it) })
30
+
31
+ actual suspend fun signOut () = ios.throwError { signOut(it) }.run { Unit }
27
32
28
- actual suspend fun signOut () {
33
+ actual val authStateChanged get() = callbackFlow {
34
+ val handle = ios.addAuthStateDidChangeListener { _, user -> offer(user?.let { FirebaseUser (it) }) }
35
+ awaitClose { ios.removeAuthStateDidChangeListener(handle) }
29
36
}
30
37
}
31
38
32
- actual class AuthResult {
39
+ actual class AuthResult internal constructor( val ios : FIRAuthDataResult ) {
33
40
actual val user: FirebaseUser ?
34
- get() = TODO ( " not implemented " ) // To change initializer of created properties use File | Settings | File Templates.
41
+ get() = ios.user?. let { FirebaseUser (it) }
35
42
}
36
43
37
- actual class FirebaseUser {
44
+ actual class FirebaseUser internal constructor( val ios : FIRUser ) {
38
45
actual val uid: String
39
- get() = TODO ( " not implemented " ) // To change initializer of created properties use File | Settings | File Templates.
46
+ get() = ios.uid
40
47
actual val isAnonymous: Boolean
41
- get() = TODO (" not implemented" ) // To change initializer of created properties use File | Settings | File Templates.
48
+ get() = ios.isAnonymous()
49
+ actual suspend fun delete () = ios.await { deleteWithCompletion(it) }.run { Unit }
50
+ actual suspend fun reload () = ios.await { reloadWithCompletion(it) }.run { Unit }
51
+ }
52
+
53
+ actual open class FirebaseAuthException (message : String ): FirebaseException(message)
54
+ actual open class FirebaseAuthActionCodeException (message : String ): FirebaseAuthException(message)
55
+ actual open class FirebaseAuthEmailException (message : String ): FirebaseAuthException(message)
56
+ actual open class FirebaseAuthInvalidCredentialsException (message : String ): FirebaseAuthException(message)
57
+ actual open class FirebaseAuthInvalidUserException (message : String ): FirebaseAuthException(message)
58
+ actual open class FirebaseAuthRecentLoginRequiredException (message : String ): FirebaseAuthException(message)
59
+ actual open class FirebaseAuthUserCollisionException (message : String ): FirebaseAuthException(message)
60
+ actual open class FirebaseAuthWebException (message : String ): FirebaseAuthException(message)
61
+
62
+
63
+ private fun <T , R > T.throwError (block : T .(errorPointer: CPointer <ObjCObjectVar <NSError ?>>) -> R ): R {
64
+ memScoped {
65
+ val errorPointer: CPointer <ObjCObjectVar <NSError ?>> = alloc<ObjCObjectVar <NSError ?>>().ptr
66
+ val result = block(errorPointer)
67
+ val error: NSError ? = errorPointer.pointed.value
68
+ if (error != null ) {
69
+ throw error.toException()
70
+ }
71
+ return result
72
+ }
73
+ }
42
74
43
- actual suspend fun delete () {
75
+ private suspend fun <T , R > T.awaitResult (function : T .(callback: (R ? , NSError ? ) -> Unit ) -> Unit ): R {
76
+ val job = CompletableDeferred <R >()
77
+ function { result, error ->
78
+ if (result != null ) {
79
+ job.complete(result)
80
+ } else if (error != null ) {
81
+ job.completeExceptionally(error.toException())
82
+ }
44
83
}
84
+ return job.await()
85
+ }
45
86
46
- actual suspend fun reload () {
87
+ private suspend fun <T > T.await (function : T .(callback: (NSError ? ) -> Unit ) -> Unit ) {
88
+ val job = CompletableDeferred <Unit >()
89
+ function { error ->
90
+ if (error == null ) {
91
+ job.complete(Unit )
92
+ } else {
93
+ job.completeExceptionally(error.toException())
94
+ }
47
95
}
96
+ job.await()
48
97
}
49
98
50
- actual open class FirebaseAuthException : FirebaseException ()
51
- actual class FirebaseAuthActionCodeException : FirebaseAuthException ()
52
- actual class FirebaseAuthEmailException : FirebaseAuthException ()
53
- actual class FirebaseAuthInvalidCredentialsException : FirebaseAuthException ()
54
- actual class FirebaseAuthInvalidUserException : FirebaseAuthException ()
55
- actual class FirebaseAuthRecentLoginRequiredException : FirebaseAuthException ()
56
- actual class FirebaseAuthUserCollisionException : FirebaseAuthException ()
57
- actual class FirebaseAuthWebException : FirebaseAuthException ()
99
+ private fun NSError.toException () = when (domain) {
100
+ FIRAuthErrorDomain -> when (code) {
101
+ FIRAuthErrorCodeInvalidActionCode ,
102
+ FIRAuthErrorCodeExpiredActionCode -> FirebaseAuthActionCodeException (toString())
103
+
104
+ FIRAuthErrorCodeInvalidEmail ,
105
+ FIRAuthErrorCodeEmailAlreadyInUse -> FirebaseAuthEmailException (toString())
106
+
107
+ FIRAuthErrorCodeInvalidCredential -> FirebaseAuthInvalidCredentialsException (toString())
108
+
109
+ FIRAuthErrorCodeInvalidUserToken -> FirebaseAuthInvalidUserException (toString())
110
+
111
+ FIRAuthErrorCodeRequiresRecentLogin -> FirebaseAuthRecentLoginRequiredException (toString())
112
+
113
+ FIRAuthErrorCodeEmailAlreadyInUse ,
114
+ FIRAuthErrorCodeAccountExistsWithDifferentCredential ,
115
+ FIRAuthErrorCodeCredentialAlreadyInUse -> FirebaseAuthUserCollisionException (toString())
116
+
117
+ FIRAuthErrorCodeWebContextAlreadyPresented ,
118
+ FIRAuthErrorCodeWebContextCancelled ,
119
+ FIRAuthErrorCodeWebInternalError -> FirebaseAuthWebException (toString())
120
+
121
+ else -> FirebaseAuthException (toString())
122
+ }
123
+ else -> FirebaseAuthException (toString())
124
+ }
0 commit comments