Skip to content

Commit

Permalink
#75 firestore 쿼리 추가 및 login flow 수정 등등
Browse files Browse the repository at this point in the history
  • Loading branch information
freeskyES committed Mar 31, 2022
1 parent a32fe39 commit c99da84
Show file tree
Hide file tree
Showing 32 changed files with 569 additions and 183 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,8 @@ interface UserDataSource {

suspend fun updateUser(profile: Profile): Result<Unit>

suspend fun findUserProfileByEmail(email: String): Result<Profile>

suspend fun logout(user: User): Result<Unit>

}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package com.nexters.checkareer.data.source.user

import com.nexters.checkareer.domain.error.ExistingUserError
import com.nexters.checkareer.domain.error.UserNotFoundError
import com.nexters.checkareer.domain.user.User
import com.nexters.checkareer.domain.user.UserRepository
import com.nexters.checkareer.domain.util.Result
Expand All @@ -27,7 +27,7 @@ class UserRepositoryImpl @Inject constructor(
local.findUserProfile().getValue()?.let {
Result.Success(it.toEntity())
}?: run {
Result.Error(ExistingUserError())
Result.Error(UserNotFoundError())
}
} catch (e: Exception) {
Result.Error(e)
Expand All @@ -36,8 +36,10 @@ class UserRepositoryImpl @Inject constructor(

override suspend fun insertUser(profile: Profile): Result<Unit> = withContext(ioDispatcher) {
return@withContext try {
local.insertUserProfile(profile)
// if (profile.user.isMember)
remote.insertUserProfile(profile)

local.insertUserProfile(profile)
} catch (e: Exception) {
Result.Error(e)
}
Expand All @@ -53,9 +55,34 @@ class UserRepositoryImpl @Inject constructor(

override suspend fun updateUser(profile: Profile): Result<Unit> = withContext(ioDispatcher) {
return@withContext try {
if (profile.user.isMember)
remote.updateUser(profile)
local.updateUser(profile)
} catch (e: Exception) {
Result.Error(e)
}
}

override suspend fun findUserProfileByEmail(email: String): Result<Profile> {
return try {
val userProfile = findUserProfile().getValue()
Result.Success(userProfile)
} catch (e: Exception) {
remote.findUserProfileByEmail(email)
}
}

override suspend fun login(profile: Profile): Result<Unit> = withContext(ioDispatcher) {
return@withContext try {
if (profile.user.isMember)
remote.insertUserProfile(profile)
local.updateUser(profile)
} catch (e: Exception) {
Result.Error(e)
}
}

override suspend fun logout(user: User): Result<Unit> {
return local.logout(user)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -84,4 +84,20 @@ class UserLocalDataSource (
Result.Error(DbError(e.toString()))
}
}

override suspend fun findUserProfileByEmail(email: String): Result<Profile> {
TODO("Not yet implemented")
}

override suspend fun logout(user: User): Result<Unit> =
withContext(ioDispatcher) {
return@withContext try {
user.toUserData().let { user ->
userDao.updateUser(user)
Result.Success(Unit)
}
} catch (e: Exception) {
Result.Error(DbError(e.toString()))
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,45 +4,97 @@ import com.google.firebase.firestore.ktx.firestore
import com.google.firebase.ktx.Firebase
import com.nexters.checkareer.data.adapter.db.data.UserProfile
import com.nexters.checkareer.data.source.user.UserDataSource
import com.nexters.checkareer.data.source.user.remote.dto.FbProfileDto
import com.nexters.checkareer.domain.error.UserNotFoundError
import com.nexters.checkareer.domain.user.User
import com.nexters.checkareer.domain.util.Result
import com.nexters.checkareer.domain.vo.Profile
import timber.log.Timber
import javax.inject.Inject
import kotlin.coroutines.resume
import kotlin.coroutines.suspendCoroutine

class UserRemoteDataSource @Inject constructor(

) : UserDataSource {

val db = Firebase.firestore

override suspend fun findUserProfile(): Result<UserProfile> {
TODO("Not yet implemented")
// TODO 가입화면 추가, 간편가입 후 프로필 생성 화면 진입
override suspend fun findUserProfileByEmail(email: String): Result<Profile> = suspendCoroutine { cont ->
try {
Timber.i("findUserProfileByEmail : $email")

val profileRef = db.collection("profiles").document("email")
profileRef
// .whereEqualTo("user.email", email)
.get()
.addOnSuccessListener { document ->
Timber.i("document : $document")
if (document != null) {
Timber.d("DocumentSnapshot data: ${document.data}")
document.toObject(FbProfileDto::class.java)?.let { result ->
Timber.d("result: $result")
cont.resume(Result.Success(result.toDomain()))
}
} else {
Timber.d( "No such document")
cont.resume(Result.Error(UserNotFoundError()))
}

}
.addOnFailureListener {
Timber.w("Error getting documents: $it")
cont.resume(Result.Error(UserNotFoundError()))
}
} catch (e: Exception) {
Result.Error(e)
}
}

override suspend fun insertUserProfile(profile: Profile): Result<Unit> {

db.collection("profiles")
.add(profile)
// profile.user.logInInfo?.email?.let { email ->
db.collection("profiles")
.document("email")
.set(profile.toFbProfile())
.addOnSuccessListener { documentReference ->
Timber.d("DocumentSnapshot added with ID: ${documentReference.id}")
Timber.d("successfully written!")
}
.addOnFailureListener { e ->
Timber.e("Error adding document $e")
Timber.e("Error writing document $e")
}
// }
return Result.Success(Unit)
}

override suspend fun updateUser(profile: Profile): Result<Unit> {

val querySnapshot = db.collection("profiles")
.whereEqualTo("user.id", profile.user.id)
.get()

Timber.i("updateUser $querySnapshot")
Timber.i("updateUser result ${querySnapshot.result}")

val resultDoc = querySnapshot.result.documents
if (resultDoc.isNotEmpty()) {
resultDoc.first().reference.update("user", profile.user)
}
return Result.Success(Unit)
}

override suspend fun deleteUserProfile(profile: Profile): Result<Unit> {
override suspend fun findUserProfile(): Result<UserProfile> {
TODO("Not yet implemented")
}

override suspend fun updateUser(profile: Profile): Result<Unit> {
override suspend fun deleteUserProfile(profile: Profile): Result<Unit> {
TODO("Not yet implemented")
}

override suspend fun findUser(): Result<User> {
TODO("Not yet implemented")
}

override suspend fun logout(user: User): Result<Unit> {
TODO("Not yet implemented")
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package com.nexters.checkareer.data.source.user.remote.dto

import com.google.gson.annotations.SerializedName
import com.nexters.checkareer.domain.skill.Skill
import com.nexters.checkareer.domain.user.User
import com.nexters.checkareer.domain.vo.LogInInfo
import com.nexters.checkareer.domain.vo.Profile
import com.nexters.checkareer.domain.vo.SkillTree

data class FbProfileDto (
@SerializedName("user") val user: FbUserDto? = null,
@SerializedName("skills") var skills: List<SkillTreeDto> = emptyList()
) {
fun toDomain(): Profile {
return Profile(
User(
user!!.id,
user.name,
true,
LogInInfo(
user.email,
user.photoUrl
)
),
skills.map {
SkillTree(
Skill(
it.skill!!.id,
it.skill.name,
it.skill.parentId,
it.skill.layer
),
it.childSkills.map { child ->
Skill(
child.id,
child.name,
child.parentId,
child.layer
)
}
)
}
)
}
}

data class FbUserDto(
@SerializedName("id") val id: String = "",
@SerializedName("name") var name: String = "",
@SerializedName("email") val email: String? = null,
@SerializedName("photoUrl") val photoUrl: String? = null
)

data class SkillTreeDto(
@SerializedName("skill") val skill: SkillDto? = null,
@SerializedName("childSkills") val childSkills: List<SkillDto> = emptyList()
)

data class SkillDto(
@SerializedName("id") val id: String = "",
@SerializedName("name") val name: String = "",
@SerializedName("parentId") val parentId: Int? = null,
@SerializedName("layer") val layer: Int = 3
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package com.nexters.checkareer.data.source.user.remote.dto

data class FbSnapShot<T>(
val value: T
)
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@ object UseCaseModule {
@Provides
fun provideDeleteProfileUseCase(
userRepository: UserRepository
): DeleteProfileUseCase {
return DeleteProfileUseCase(userRepository)
): LogoutUseCase {
return LogoutUseCase(userRepository)
}

@Provides
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
package com.nexters.checkareer.domain.error

class ExistingUserError() : Exception()
class UserNotFoundError: Exception()
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
package com.nexters.checkareer.domain.skill

import android.os.Parcelable
import com.google.gson.annotations.SerializedName
import com.nexters.checkareer.domain.vo.SkillTree
import kotlinx.parcelize.Parcelize

@Parcelize
data class Skill(
val id: String,
val name: String,
val parentId: Int? = null,
val layer: Int = 3
@SerializedName("id") val id: String,
@SerializedName("name") val name: String,
@SerializedName("parentId") val parentId: Int? = null,
@SerializedName("layer") val layer: Int = 3
): Parcelable {
fun toSkillTree(detailSkill: List<Skill>): SkillTree {
return SkillTree(this, detailSkill)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,18 @@ package com.nexters.checkareer.domain.usecase

import com.nexters.checkareer.domain.user.UserRepository
import com.nexters.checkareer.domain.util.Result
import com.nexters.checkareer.domain.util.getValue
import com.nexters.checkareer.domain.vo.Profile
import java.lang.Exception
import javax.inject.Inject

class DeleteProfileUseCase @Inject constructor(
class LogoutUseCase @Inject constructor(
private val userRepository: UserRepository
) {
suspend operator fun invoke(profile: Profile): Result<Unit> {
suspend operator fun invoke(): Result<Unit> {
return try {
userRepository.deleteUser(profile)
val profile = userRepository.findUserProfile().getValue()
userRepository.logout(profile.user.copy(isMember = false, logInInfo = null))
Result.Success(Unit)
} catch (e: Exception) {
println(e.message)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,23 @@ import com.nexters.checkareer.domain.util.getValue
import com.nexters.checkareer.domain.vo.LogInInfo
import com.nexters.checkareer.domain.vo.Profile
import java.lang.Exception
import java.security.InvalidParameterException
import javax.inject.Inject

class SignInUseCase @Inject constructor(
private val userRepository: UserRepository
) {
suspend operator fun invoke(logInInfo: LogInInfo): Result<Unit> {
return try {
val user = userRepository.findUserProfile().getValue()
logInInfo.email?.let {
val user = userRepository.findUserProfileByEmail(it).getValue()

val modifiedUser = Profile(user.user.copy(logInInfo = logInInfo), user.skills)
userRepository.updateUser(modifiedUser)
val modifiedUser = Profile(user.user.copy(logInInfo = logInInfo, isMember = true), user.skills)
userRepository.updateUser(modifiedUser)

Result.Success(Unit)
}?: Result.Error(InvalidParameterException())

Result.Success(Unit)
} catch (e: Exception) {
println(e.message)
Result.Error(e)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,9 @@ interface UserRepository {

suspend fun deleteUser(profile: Profile): Result<Unit>

suspend fun findUserProfileByEmail(email: String): Result<Profile>

suspend fun login(profile: Profile): Result<Unit>

suspend fun logout(user: User): Result<Unit>
}
Loading

0 comments on commit c99da84

Please sign in to comment.