#44 first try at firebase use-cases
This commit is contained in:
		
							parent
							
								
									27c45842f2
								
							
						
					
					
						commit
						46824f4498
					
				
					 16 changed files with 294 additions and 7 deletions
				
			
		|  | @ -0,0 +1,3 @@ | |||
| package be.ugent.sel.studeez.data.local.models | ||||
| 
 | ||||
| data class User(val id: String = "", val isAnonymous: Boolean = true) | ||||
							
								
								
									
										27
									
								
								app/src/main/java/be/ugent/sel/studeez/domain/Performance.kt
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								app/src/main/java/be/ugent/sel/studeez/domain/Performance.kt
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,27 @@ | |||
| /* | ||||
| Copyright 2022 Google LLC | ||||
| 
 | ||||
| Licensed under the Apache License, Version 2.0 (the "License"); | ||||
| you may not use this file except in compliance with the License. | ||||
| You may obtain a copy of the License at | ||||
| 
 | ||||
|     https://www.apache.org/licenses/LICENSE-2.0 | ||||
| 
 | ||||
| Unless required by applicable law or agreed to in writing, software | ||||
| distributed under the License is distributed on an "AS IS" BASIS, | ||||
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
| See the License for the specific language governing permissions and | ||||
| limitations under the License. | ||||
|  */ | ||||
| 
 | ||||
| package be.ugent.sel.studeez.domain | ||||
| 
 | ||||
| import com.google.firebase.perf.ktx.trace | ||||
| import com.google.firebase.perf.metrics.Trace | ||||
| 
 | ||||
| /** | ||||
|  * Trace a block with Firebase performance. | ||||
|  * | ||||
|  * Supports both suspend and regular methods. | ||||
|  */ | ||||
| inline fun <T> trace(name: String, block: Trace.() -> T): T = Trace.create(name).trace(block) | ||||
|  | @ -0,0 +1,34 @@ | |||
| /* | ||||
| Copyright 2022 Google LLC | ||||
| 
 | ||||
| Licensed under the Apache License, Version 2.0 (the "License"); | ||||
| you may not use this file except in compliance with the License. | ||||
| You may obtain a copy of the License at | ||||
| 
 | ||||
|     https://www.apache.org/licenses/LICENSE-2.0 | ||||
| 
 | ||||
| Unless required by applicable law or agreed to in writing, software | ||||
| distributed under the License is distributed on an "AS IS" BASIS, | ||||
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
| See the License for the specific language governing permissions and | ||||
| limitations under the License. | ||||
|  */ | ||||
| 
 | ||||
| package be.ugent.sel.studeez.domain.account | ||||
| 
 | ||||
| import be.ugent.sel.studeez.data.local.models.User | ||||
| import kotlinx.coroutines.flow.Flow | ||||
| 
 | ||||
| interface AccountService { | ||||
|     val currentUserId: String | ||||
|     val hasUser: Boolean | ||||
| 
 | ||||
|     val currentUser: Flow<User> | ||||
| 
 | ||||
|     suspend fun authenticate(email: String, password: String) | ||||
|     suspend fun sendRecoveryEmail(email: String) | ||||
|     suspend fun createAnonymousAccount() | ||||
|     suspend fun linkAccount(email: String, password: String) | ||||
|     suspend fun deleteAccount() | ||||
|     suspend fun signOut() | ||||
| } | ||||
|  | @ -0,0 +1,84 @@ | |||
| /* | ||||
| Copyright 2022 Google LLC | ||||
| 
 | ||||
| Licensed under the Apache License, Version 2.0 (the "License"); | ||||
| you may not use this file except in compliance with the License. | ||||
| You may obtain a copy of the License at | ||||
| 
 | ||||
|     https://www.apache.org/licenses/LICENSE-2.0 | ||||
| 
 | ||||
| Unless required by applicable law or agreed to in writing, software | ||||
| distributed under the License is distributed on an "AS IS" BASIS, | ||||
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
| See the License for the specific language governing permissions and | ||||
| limitations under the License. | ||||
|  */ | ||||
| 
 | ||||
| package be.ugent.sel.studeez.domain.account | ||||
| 
 | ||||
| import be.ugent.sel.studeez.data.local.models.User | ||||
| import be.ugent.sel.studeez.domain.trace | ||||
| import com.google.firebase.auth.EmailAuthProvider | ||||
| import com.google.firebase.auth.FirebaseAuth | ||||
| import kotlinx.coroutines.channels.awaitClose | ||||
| import kotlinx.coroutines.flow.Flow | ||||
| import kotlinx.coroutines.flow.callbackFlow | ||||
| import kotlinx.coroutines.tasks.await | ||||
| import javax.inject.Inject | ||||
| 
 | ||||
| class AccountServiceImpl @Inject constructor( | ||||
|     private val auth: FirebaseAuth | ||||
| ) : AccountService { | ||||
| 
 | ||||
|     override val currentUserId: String | ||||
|         get() = auth.currentUser?.uid.orEmpty() | ||||
| 
 | ||||
|     override val hasUser: Boolean | ||||
|         get() = auth.currentUser != null | ||||
| 
 | ||||
|     override val currentUser: Flow<User> | ||||
|         get() = callbackFlow { | ||||
|             val listener = | ||||
|                 FirebaseAuth.AuthStateListener { auth -> | ||||
|                     this.trySend(auth.currentUser?.let { User(it.uid, it.isAnonymous) } ?: User()) | ||||
|                 } | ||||
|             auth.addAuthStateListener(listener) | ||||
|             awaitClose { auth.removeAuthStateListener(listener) } | ||||
|         } | ||||
| 
 | ||||
|     override suspend fun authenticate(email: String, password: String) { | ||||
|         auth.signInWithEmailAndPassword(email, password).await() | ||||
|     } | ||||
| 
 | ||||
|     override suspend fun sendRecoveryEmail(email: String) { | ||||
|         auth.sendPasswordResetEmail(email).await() | ||||
|     } | ||||
| 
 | ||||
|     override suspend fun createAnonymousAccount() { | ||||
|         auth.signInAnonymously().await() | ||||
|     } | ||||
| 
 | ||||
|     override suspend fun linkAccount(email: String, password: String): Unit = | ||||
|         trace(LINK_ACCOUNT_TRACE) { | ||||
|             val credential = EmailAuthProvider.getCredential(email, password) | ||||
|             auth.currentUser!!.linkWithCredential(credential).await() | ||||
|         } | ||||
| 
 | ||||
|     override suspend fun deleteAccount() { | ||||
|         auth.currentUser!!.delete().await() | ||||
|     } | ||||
| 
 | ||||
|     override suspend fun signOut() { | ||||
|         if (auth.currentUser!!.isAnonymous) { | ||||
|             auth.currentUser!!.delete() | ||||
|         } | ||||
|         auth.signOut() | ||||
| 
 | ||||
|         // Sign the user back in anonymously. | ||||
|         createAnonymousAccount() | ||||
|     } | ||||
| 
 | ||||
|     companion object { | ||||
|         private const val LINK_ACCOUNT_TRACE = "linkAccount" | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,13 @@ | |||
| package be.ugent.sel.studeez.domain.account | ||||
| 
 | ||||
| import com.google.firebase.auth.FirebaseAuth | ||||
| import kotlinx.coroutines.tasks.await | ||||
| import javax.inject.Inject | ||||
| 
 | ||||
| class AuthenticateUseCase @Inject constructor( | ||||
|     private val auth: FirebaseAuth, | ||||
| ) { | ||||
|     suspend operator fun invoke(email: String, password: String) { | ||||
|         auth.signInWithEmailAndPassword(email, password).await() | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,13 @@ | |||
| package be.ugent.sel.studeez.domain.account | ||||
| 
 | ||||
| import com.google.firebase.auth.FirebaseAuth | ||||
| import kotlinx.coroutines.tasks.await | ||||
| import javax.inject.Inject | ||||
| 
 | ||||
| class CreateAnonymousAccountUseCase @Inject constructor( | ||||
|     private val auth: FirebaseAuth, | ||||
| ) { | ||||
|     suspend operator fun invoke() { | ||||
|         auth.signInAnonymously().await() | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,13 @@ | |||
| package be.ugent.sel.studeez.domain.account | ||||
| 
 | ||||
| import com.google.firebase.auth.FirebaseAuth | ||||
| import kotlinx.coroutines.tasks.await | ||||
| import javax.inject.Inject | ||||
| 
 | ||||
| class DeleteAccountUseCase @Inject constructor( | ||||
|     private val auth: FirebaseAuth, | ||||
| ) { | ||||
|     suspend operator fun invoke() { | ||||
|         auth.currentUser!!.delete().await() | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,22 @@ | |||
| package be.ugent.sel.studeez.domain.account | ||||
| 
 | ||||
| import be.ugent.sel.studeez.domain.trace | ||||
| import com.google.firebase.auth.EmailAuthProvider | ||||
| import com.google.firebase.auth.FirebaseAuth | ||||
| import kotlinx.coroutines.tasks.await | ||||
| import javax.inject.Inject | ||||
| 
 | ||||
| class LinkAccountUseCase @Inject constructor( | ||||
|     private val auth: FirebaseAuth, | ||||
| ) { | ||||
| 
 | ||||
|     suspend operator fun invoke(email: String, password: String): Unit = | ||||
|         trace(LINK_ACCOUNT_TRACE) { | ||||
|             val credential = EmailAuthProvider.getCredential(email, password) | ||||
|             auth.currentUser!!.linkWithCredential(credential).await() | ||||
|         } | ||||
| 
 | ||||
|     companion object { | ||||
|         private const val LINK_ACCOUNT_TRACE = "linkAccount" | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,13 @@ | |||
| package be.ugent.sel.studeez.domain.account | ||||
| 
 | ||||
| import com.google.firebase.auth.FirebaseAuth | ||||
| import kotlinx.coroutines.tasks.await | ||||
| import javax.inject.Inject | ||||
| 
 | ||||
| class SendRecoveryEmailUseCase @Inject constructor( | ||||
|     private val auth: FirebaseAuth, | ||||
| ) { | ||||
|     suspend operator fun invoke(email: String) { | ||||
|         auth.sendPasswordResetEmail(email).await() | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,18 @@ | |||
| package be.ugent.sel.studeez.domain.account | ||||
| 
 | ||||
| import com.google.firebase.auth.FirebaseAuth | ||||
| import javax.inject.Inject | ||||
| 
 | ||||
| class SignOutUseCase @Inject constructor( | ||||
|     private val auth: FirebaseAuth, | ||||
|     private val createAnonymousAccountUseCase: CreateAnonymousAccountUseCase, | ||||
| ) { | ||||
|     suspend operator fun invoke() { | ||||
|         if (auth.currentUser!!.isAnonymous) { | ||||
|             auth.currentUser!!.delete() | ||||
|         } | ||||
|         auth.signOut() | ||||
| 
 | ||||
|         createAnonymousAccountUseCase() | ||||
|     } | ||||
| } | ||||
		Reference in a new issue
	
	 reyniersbram
						reyniersbram