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