Skip to content

Commit

Permalink
feat: login 로직 추가 #52
Browse files Browse the repository at this point in the history
  • Loading branch information
easyhz committed Aug 12, 2024
1 parent 697dee3 commit d8e4d4b
Show file tree
Hide file tree
Showing 16 changed files with 227 additions and 6 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.easyhz.noffice.core.network.api.auth

import com.easyhz.noffice.core.network.model.request.sign.LoginRequest
import com.easyhz.noffice.core.network.model.response.auth.UserResponse
import retrofit2.http.Body
import retrofit2.http.POST

interface AuthService {
@POST("/api/v1/member/login")
suspend fun login(
@Body body: LoginRequest
): Result<UserResponse>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.easyhz.noffice.core.network.di.service

import com.easyhz.noffice.core.network.api.auth.AuthService
import com.easyhz.noffice.core.network.di.NofficeRetrofit
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import retrofit2.Retrofit

@Module
@InstallIn(SingletonComponent::class)
object AuthModule {
@Provides
fun provideAuthService(@NofficeRetrofit retrofit: Retrofit): AuthService =
retrofit.create(AuthService::class.java)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package com.easyhz.noffice.core.network.model.request.sign

data class LoginRequest(
val code: String,
val provider: String
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package com.easyhz.noffice.core.network.model.response.auth

data class TokenResponse(
val accessToken: String,
val refreshToken: String
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.easyhz.noffice.core.network.model.response.auth

data class UserResponse(
val memberId: String,
val memberName: String,
val provider: String,
val token: TokenResponse
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.easyhz.noffice.data.auth.di.repository

import com.easyhz.noffice.data.auth.repository.login.LoginRepository
import com.easyhz.noffice.data.auth.repository.login.LoginRepositoryIml
import dagger.Binds
import dagger.Module
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent

@Module
@InstallIn(SingletonComponent::class)
interface AuthRepositoryModule {

@Binds
fun bindAuthRepository(
loginRepositoryIml: LoginRepositoryIml
): LoginRepository
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.easyhz.noffice.data.auth.di.strategy

import com.easyhz.noffice.data.auth.strategy.BaseStrategy
import com.easyhz.noffice.data.auth.strategy.GoogleStrategy
import dagger.Binds
import dagger.Module
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import javax.inject.Singleton

@Module
@InstallIn(SingletonComponent::class)
abstract class LoginStrategyModule {

@Binds
@Singleton
abstract fun bindGoogleStrategy(
googleStrategy: GoogleStrategy
): BaseStrategy
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.easyhz.noffice.data.auth.repository.login

import android.content.Context

interface LoginRepository {
suspend fun loginWithGoogle(context: Context): Result<Unit>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package com.easyhz.noffice.data.auth.repository.login

import android.content.Context
import com.easyhz.noffice.core.network.api.auth.AuthService
import com.easyhz.noffice.core.network.model.request.sign.LoginRequest
import com.easyhz.noffice.data.auth.strategy.GoogleStrategy
import com.easyhz.noffice.data.auth.util.Provider
import javax.inject.Inject

class LoginRepositoryIml @Inject constructor(
private val googleStrategy: GoogleStrategy,
private val authService: AuthService
): LoginRepository {
override suspend fun loginWithGoogle(context: Context): Result<Unit> = runCatching {
val authorizationCode = googleStrategy.login(context).getOrThrow()
val request = LoginRequest(
code = authorizationCode,
provider = Provider.GOOGLE.name
)

val a = authService.login(request).getOrThrow()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.easyhz.noffice.data.auth.strategy

import android.content.Context

interface BaseStrategy {

suspend fun login(context: Context): Result<String>

suspend fun logout()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package com.easyhz.noffice.data.auth.strategy

import android.content.Context
import android.util.Log
import androidx.credentials.CredentialManager
import androidx.credentials.CustomCredential
import androidx.credentials.GetCredentialRequest
import androidx.credentials.GetCredentialResponse
import com.easyhz.noffice.core.common.error.NofficeError
import com.easyhz.noffice.data.auth.BuildConfig
import com.google.android.libraries.identity.googleid.GetGoogleIdOption
import com.google.android.libraries.identity.googleid.GoogleIdTokenCredential
import com.google.android.libraries.identity.googleid.GoogleIdTokenParsingException
import javax.inject.Inject

class GoogleStrategy @Inject constructor(
): BaseStrategy {
private val tag = this.javaClass.name

override suspend fun login(context: Context): Result<String> = runCatching {
val googleIdOption: GetGoogleIdOption = GetGoogleIdOption.Builder()
.setServerClientId(BuildConfig.GOOGLE_CLIENT_ID)
.setFilterByAuthorizedAccounts(false)
.setAutoSelectEnabled(false)
.build()

val request: GetCredentialRequest =
GetCredentialRequest.Builder().addCredentialOption(
googleIdOption
).build()

val result =
CredentialManager.create(context)
.getCredential(context = context, request = request)
handleGoogleSignIn(result)
}

override suspend fun logout() {
TODO("Not yet implemented")
}

private fun handleGoogleSignIn(result: GetCredentialResponse): String {
when (val credential = result.credential) {
is CustomCredential -> {
if (credential.type == GoogleIdTokenCredential.TYPE_GOOGLE_ID_TOKEN_CREDENTIAL) {
try {
val googleIdTokenCredential = GoogleIdTokenCredential
.createFrom(credential.data)
return googleIdTokenCredential.idToken
} catch (e: GoogleIdTokenParsingException) {
throw e
}
} else {
Log.d(tag, "Unexpected type of credential (not TYPE_GOOGLE_ID_TOKEN_CREDENTIAL). ")
throw NofficeError.UnexpectedError
}
}
else -> {
Log.d(tag, "Unexpected type of credential (not custom).")
throw NofficeError.UnexpectedError
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package com.easyhz.noffice.data.auth.util

enum class Provider {
GOOGLE
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.easyhz.noffice.domain.sign.usecase

import android.content.Context
import com.easyhz.noffice.core.common.base.BaseUseCase
import com.easyhz.noffice.data.auth.repository.login.LoginRepository
import javax.inject.Inject

class LoginUseCase @Inject constructor(
private val loginRepository: LoginRepository
): BaseUseCase<Context, Unit>() {
override suspend fun invoke(param: Context): Result<Unit> =
loginRepository.loginWithGoogle(param)
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
package com.easyhz.noffice.feature.sign.contract.login

import android.content.Context
import com.easyhz.noffice.core.common.base.UiIntent

sealed class LoginIntent : UiIntent() {
data object ClickToLogInWithGoogle: LoginIntent()
data class ClickToLogInWithGoogle(val context: Context): LoginIntent()
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
Expand All @@ -29,6 +30,7 @@ fun LoginScreen(
viewModel: LoginViewModel = hiltViewModel(),
navigateToHome: () -> Unit
) {
val context = LocalContext.current
NofficeBasicScaffold {
Box(modifier = modifier.fillMaxSize()) {
Image(
Expand Down Expand Up @@ -59,7 +61,7 @@ fun LoginScreen(
.weight(0.2f),
onClickSocial = object :SocialLoginType.OnItemClickListener {
override fun onClickGoogle() {
viewModel.postIntent(LoginIntent.ClickToLogInWithGoogle)
viewModel.postIntent(LoginIntent.ClickToLogInWithGoogle(context))
}
}
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,28 +3,36 @@ package com.easyhz.noffice.feature.sign.screen.login
import android.content.Context
import androidx.lifecycle.viewModelScope
import com.easyhz.noffice.core.common.base.BaseViewModel
import com.easyhz.noffice.domain.sign.usecase.LoginUseCase
import com.easyhz.noffice.feature.sign.contract.login.LoginIntent
import com.easyhz.noffice.feature.sign.contract.login.LoginSideEffect
import com.easyhz.noffice.feature.sign.contract.login.LoginState
import dagger.hilt.android.lifecycle.HiltViewModel
import dagger.hilt.android.qualifiers.ApplicationContext
import kotlinx.coroutines.launch
import javax.inject.Inject

@HiltViewModel
class LoginViewModel @Inject constructor(
@ApplicationContext private val context: Context
private val loginUseCase: LoginUseCase
): BaseViewModel<LoginState, LoginIntent, LoginSideEffect>(
initialState = LoginState.init()
) {
override fun handleIntent(intent: LoginIntent) {
when(intent) {
is LoginIntent.ClickToLogInWithGoogle -> { onClickToLogInWithGoogle() }
is LoginIntent.ClickToLogInWithGoogle -> { onClickToLogInWithGoogle(intent.context) }
}
}

private fun onClickToLogInWithGoogle() = viewModelScope.launch {
private fun onClickToLogInWithGoogle(context: Context) = viewModelScope.launch {
// TODO 로그인 로직 처리
loginUseCase.invoke(context).onSuccess {
println("success")
}.onFailure {
it.printStackTrace()
}
}

private fun navigateToHome() {
postSideEffect { LoginSideEffect.NavigateToHome }
}
}

0 comments on commit d8e4d4b

Please sign in to comment.