Skip to content

Commit

Permalink
#219 사용자 상세 정보(CognitoUserDetails)를 로그인시에 가져오도록 수정
Browse files Browse the repository at this point in the history
  • Loading branch information
pknujsp committed Mar 11, 2024
1 parent 1bca783 commit ad97ca5
Show file tree
Hide file tree
Showing 8 changed files with 166 additions and 85 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import kotlinx.coroutines.flow.StateFlow

interface AccountSessionRepository {
val lastSavedEmail: Flow<String>
val userOnCurrentSession: StateFlow<UserEntity?>
val userOnCurrentSession: Flow<UserEntity?>
val session: StateFlow<CognitoUserSession?>

val signedIn: Boolean
Expand Down
Original file line number Diff line number Diff line change
@@ -1,21 +1,34 @@
package com.android.mediproject.core.data.session

import com.amazonaws.mobileconnectors.cognitoidentityprovider.CognitoDevice
import com.amazonaws.mobileconnectors.cognitoidentityprovider.CognitoUserPool
import com.amazonaws.mobileconnectors.cognitoidentityprovider.CognitoUserSession
import com.amazonaws.mobileconnectors.cognitoidentityprovider.continuations.AuthenticationContinuation
import com.amazonaws.mobileconnectors.cognitoidentityprovider.continuations.ChallengeContinuation
import com.amazonaws.mobileconnectors.cognitoidentityprovider.continuations.MultiFactorAuthenticationContinuation
import com.amazonaws.mobileconnectors.cognitoidentityprovider.handlers.AuthenticationHandler
import com.android.mediproject.core.datastore.AppDataStore
import com.android.mediproject.core.model.user.UserEntity
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlin.coroutines.resume
import kotlin.coroutines.suspendCoroutine

class AccountSessionRepositoryImpl(
private val appDataStore: AppDataStore,
private val userPool: CognitoUserPool,
) : AccountSessionRepository {
override val lastSavedEmail = appDataStore.userEmail.distinctUntilChanged()

private val mutableUserOnCurrentSession = MutableStateFlow<UserEntity?>(null)
override val userOnCurrentSession = mutableUserOnCurrentSession.asStateFlow()
override val userOnCurrentSession = appDataStore.userEmail.combine(appDataStore.nickName) { email, nickName ->
if (email.isEmpty() || nickName.isEmpty()) {
null
} else {
UserEntity(nickName, email)
}
}

private var mutableSession = MutableStateFlow<CognitoUserSession?>(null)
override val session = mutableSession.asStateFlow()
Expand All @@ -25,20 +38,40 @@ class AccountSessionRepositoryImpl(

override suspend fun updateSession(session: CognitoUserSession?) {
mutableSession.value = session

if (session == null) {
mutableUserOnCurrentSession.value = null
appDataStore.clearMyAccountInfo()
}
}

override suspend fun updateAccount(email: String, nickName: String) {
mutableUserOnCurrentSession.value = UserEntity(email, nickName)
appDataStore.saveMyAccountInfo(email, nickName)
}

override suspend fun loadSession() {
suspendCoroutine {
userPool.currentUser?.getSession(
object : AuthenticationHandler {
override fun onSuccess(userSession: CognitoUserSession?, newDevice: CognitoDevice?) {
it.resume(userSession)
}

override fun getAuthenticationDetails(authenticationContinuation: AuthenticationContinuation?, userId: String?) {
}

override fun getMFACode(continuation: MultiFactorAuthenticationContinuation?) {
}

override fun authenticationChallenge(continuation: ChallengeContinuation?) {
}

override fun onFailure(exception: Exception?) {
it.resume(null)
}
},
)
}.let { session ->
mutableSession.value = session
}
}

}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package com.android.mediproject.core.model.user

data class UserEntity(
val nickName: String,
val email: String,
val nickName: String = "",
val email: String = "",
)
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.android.mediproject.core.network.datasource.sign

import com.amazonaws.mobileconnectors.cognitoidentityprovider.CognitoDevice
import com.amazonaws.mobileconnectors.cognitoidentityprovider.CognitoUserDetails
import com.amazonaws.mobileconnectors.cognitoidentityprovider.CognitoUserSession

interface LoginDataSource {
Expand All @@ -15,5 +16,6 @@ class LoginRequest(

class LoginResponse(
val userSession: CognitoUserSession,
val newDevice: CognitoDevice?,
val attr: CognitoUserDetails,
val newDevice: CognitoDevice? = null,
)
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
package com.android.mediproject.core.network.datasource.sign

import com.amazonaws.mobileconnectors.cognitoidentityprovider.CognitoDevice
import com.amazonaws.mobileconnectors.cognitoidentityprovider.CognitoUserDetails
import com.amazonaws.mobileconnectors.cognitoidentityprovider.CognitoUserPool
import com.amazonaws.mobileconnectors.cognitoidentityprovider.CognitoUserSession
import com.amazonaws.mobileconnectors.cognitoidentityprovider.continuations.AuthenticationContinuation
import com.amazonaws.mobileconnectors.cognitoidentityprovider.continuations.AuthenticationDetails
import com.amazonaws.mobileconnectors.cognitoidentityprovider.continuations.ChallengeContinuation
import com.amazonaws.mobileconnectors.cognitoidentityprovider.continuations.MultiFactorAuthenticationContinuation
import com.amazonaws.mobileconnectors.cognitoidentityprovider.handlers.AuthenticationHandler
import com.amazonaws.mobileconnectors.cognitoidentityprovider.handlers.GetDetailsHandler
import kotlin.coroutines.resume
import kotlin.coroutines.suspendCoroutine

Expand All @@ -16,15 +18,33 @@ class LoginDataSourceImpl(
private val userPool: CognitoUserPool,
) : LoginDataSource {

override suspend fun login(request: LoginRequest): Result<LoginResponse> = suspendCoroutine { continuation ->
override suspend fun login(request: LoginRequest): Result<LoginResponse> {
val session = getSession(request)
session.fold(
onSuccess = { userSession ->
val attr = getUserAttr(userSession)
return attr.fold(
onSuccess = { userAttr ->
Result.success(LoginResponse(userSession, userAttr))
},
onFailure = { Result.failure(it) },
)
},
onFailure = { return Result.failure(it) },
)
}

override suspend fun logout() = userPool.currentUser.signOut()

private suspend fun getSession(request: LoginRequest) = suspendCoroutine<Result<CognitoUserSession>> {
userPool.getUser(request.email).getSession(
object : AuthenticationHandler {
override fun onSuccess(userSession: CognitoUserSession, newDevice: CognitoDevice?) {
continuation.resume(Result.success(LoginResponse(userSession, newDevice)))
it.resume(Result.success(userSession))
}

override fun onFailure(exception: Exception) {
continuation.resume(Result.failure(exception))
it.resume(Result.failure(exception))
// UserNotConfirmedException : 이메일 인증을 하지 않았을 때 발생
}

Expand All @@ -51,5 +71,17 @@ class LoginDataSourceImpl(
)
}

override suspend fun logout() = userPool.currentUser.signOut()
private suspend fun getUserAttr(session: CognitoUserSession) = suspendCoroutine<Result<CognitoUserDetails>> {
userPool.getUser(session.username).getDetails(
object : GetDetailsHandler {
override fun onSuccess(cognitoUserDetails: CognitoUserDetails) {
it.resume(Result.success(cognitoUserDetails))
}

override fun onFailure(exception: Exception) {
it.resume(Result.failure(exception))
}
},
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ interface SignupDataSource {
suspend fun resendConfirmationCode(cognitoUser: CognitoUser): Result<ConfirmationCodeDeliveryDetails>
}

private const val USER_NAME = "custom:user_name"
private const val CUSTOM_USER_NAME = "custom:user_name"

class SignUpRequest(
val email: String,
Expand All @@ -20,7 +20,7 @@ class SignUpRequest(
val passwordString: String get() = password.decodeToString()

val attr = CognitoUserAttributes().apply {
addAttribute(USER_NAME, nickName)
addAttribute(CUSTOM_USER_NAME, nickName)
}
}

Expand Down
Loading

0 comments on commit ad97ca5

Please sign in to comment.