Skip to content

Commit

Permalink
fix auth
Browse files Browse the repository at this point in the history
  • Loading branch information
stslex committed Aug 30, 2023
1 parent a7a6ac9 commit 743af97
Show file tree
Hide file tree
Showing 33 changed files with 438 additions and 360 deletions.
15 changes: 10 additions & 5 deletions app/src/main/java/com/stslex/aproselection/ui/InitialApp.kt
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.unit.dp
import androidx.navigation.NavHostController
import com.stslex.aproselection.core.navigation.destination.AppDestination
import com.stslex.aproselection.core.navigation.ext.NavExt.isAuth
import com.stslex.aproselection.core.ui.ext.noRippleClick
import com.stslex.aproselection.core.ui.theme.AppDimens
import com.stslex.aproselection.navigation.NavigationHost
Expand All @@ -48,17 +47,22 @@ fun InitialApp(
val isInitialAuth by remember {
viewModel.isInitialAuth
}.collectAsState()
var isAuth by remember {
mutableStateOf(false)
}

LaunchedEffect(Unit) {
viewModel.init()
}

navController.addOnDestinationChangedListener { _, destination, _ ->
isAuth = destination.route != AppDestination.AUTH.navigationRoute
}

AppDestination
.getStartDestination(isInitialAuth)
?.let { destination ->
AppContainer(
isAuth = navController.isAuth
) {
AppContainer(isAuth = isAuth) {
NavigationHost(
navController = navController,
startDestination = destination
Expand All @@ -85,7 +89,8 @@ fun AppContainer(
AppDrawerState.OPEN -> 0.dp
AppDrawerState.CLOSE -> -screenWidth * 0.3f
},
animationSpec = tween(500)
animationSpec = tween(500),
label = "drawer animation"
)

BackHandler(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
package com.stslex.aproselection.ui

import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.stslex.aproselection.controller.AuthController
import com.stslex.aproselection.core.navigation.destination.NavigationScreen
import com.stslex.aproselection.core.navigation.navigator.Navigator
import com.stslex.aproselection.core.ui.base.BaseViewModel
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
Expand All @@ -14,7 +14,7 @@ import kotlinx.coroutines.flow.onEach
class InitialAppViewModel(
private val navigator: Navigator,
private val controller: AuthController
) : BaseViewModel() {
) : ViewModel() {

private val _isInitialAuth = MutableStateFlow<Boolean?>(null)
val isInitialAuth: StateFlow<Boolean?>
Expand Down
41 changes: 37 additions & 4 deletions app/src/test/java/com/stslex/aproselection/DiKoinModuleTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -10,22 +10,38 @@ import com.stslex.aproselection.di.appModule
import com.stslex.aproselection.di.initialAppModule
import com.stslex.aproselection.feature.auth.di.ModuleFeatureAuth.moduleFeatureAuth
import com.stslex.aproselection.feature.home.di.moduleFeatureHome
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.StandardTestDispatcher
import kotlinx.coroutines.test.TestDispatcher
import kotlinx.coroutines.test.resetMain
import kotlinx.coroutines.test.setMain
import org.junit.Rule
import org.junit.Test
import org.koin.android.ext.koin.androidContext
import org.junit.rules.TestWatcher
import org.junit.runner.Description
import org.koin.dsl.koinApplication
import org.koin.test.KoinTest
import org.koin.test.check.checkModules
import org.koin.test.mock.MockProviderRule
import org.mockito.Mockito

class DiKoinModuleTest : KoinTest {

@ExperimentalCoroutinesApi
@get:Rule
val mainCoroutineRule = MainCoroutineRule()

@get:Rule
val mockProvider = MockProviderRule.create { clazz ->
Mockito.mock(clazz.java)
}

@Test
fun checkKoinModules() {
val navController = Mockito.mock(NavHostController::class.java)

koinApplication {

androidContext(Mockito.mock(Context::class.java))
modules(
moduleCoreNavigation(navController),
initialAppModule,
Expand All @@ -36,7 +52,24 @@ class DiKoinModuleTest : KoinTest {
moduleFeatureAuth,
moduleFeatureHome,
)
checkModules()
checkModules {
withInstance<Context>()
}
}
}
}

@ExperimentalCoroutinesApi
class MainCoroutineRule(private val dispatcher: TestDispatcher = StandardTestDispatcher()) :
TestWatcher() {

override fun starting(description: Description?) {
super.starting(description)
Dispatchers.setMain(dispatcher)
}

override fun finished(description: Description?) {
super.finished(description)
Dispatchers.resetMain()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,5 @@ object NavExt {
}

val NavController.isAuth: Boolean
get() = currentDestination?.route != AppDestination.AUTH.route
get() = currentDestination?.route != AppDestination.AUTH.navigationRoute
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ package com.stslex.aproselection.core.network.client

import com.stslex.aproselection.core.datastore.AppDataStore
import com.stslex.aproselection.core.network.BuildConfig
import com.stslex.aproselection.core.network.clients.auth.model.UserAuthResponseModel
import com.stslex.aproselection.core.network.clients.auth.model.UserAuthRequestModel
import com.stslex.aproselection.core.network.clients.auth.model.UserAuthResponseModel
import com.stslex.aproselection.core.network.model.ApiError
import com.stslex.aproselection.core.network.model.ApiErrorRespond
import com.stslex.aproselection.core.network.model.ApiErrorType
Expand All @@ -27,9 +27,9 @@ import io.ktor.client.request.post
import io.ktor.client.request.setBody
import io.ktor.http.ContentType
import io.ktor.http.URLProtocol
import io.ktor.http.appendPathSegments
import io.ktor.http.contentType
import io.ktor.http.encodedPath
import io.ktor.http.path
import io.ktor.serialization.kotlinx.json.json
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
Expand Down Expand Up @@ -76,7 +76,7 @@ class NetworkClientImpl(

override val apiClient: HttpClient = client.config {
defaultRequest {
url {
url("${BuildConfig.API_SERVER_HOST}") {
host = BuildConfig.API_SERVER_HOST
encodedPath = BuildConfig.API_VERSION
protocol = URLProtocol.HTTP
Expand All @@ -100,9 +100,7 @@ class NetworkClientImpl(
)

when (apiError.type) {
is ApiErrorType.Unauthorized.Token -> {
dataStore.setToken(auth().token)
}
is ApiErrorType.Unauthorized.Token -> auth()

else -> throw apiError
}
Expand All @@ -122,10 +120,15 @@ class NetworkClientImpl(
username = dataStore.credential.value.username,
password = dataStore.credential.value.password
)
apiClient.post {
url.appendPathSegments("passport/login")
setBody<UserAuthRequestModel>(user)
}.body<UserAuthResponseModel>()
apiClient
.post {
url.path("passport/login")
setBody<UserAuthRequestModel>(user)
}
.body<UserAuthResponseModel>()
.also { authModel ->
dataStore.setToken(token = authModel.token)
}
}

companion object {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,12 @@ package com.stslex.aproselection.core.network.clients.auth

import com.stslex.aproselection.core.datastore.AppDataStore
import com.stslex.aproselection.core.network.client.NetworkClient
import com.stslex.aproselection.core.network.clients.auth.model.HelloRequestModel
import com.stslex.aproselection.core.network.clients.auth.model.UserAuthResponseModel
import com.stslex.aproselection.core.network.clients.auth.model.UserAuthRequestModel
import com.stslex.aproselection.core.network.clients.auth.model.UserAuthResponseModel
import com.stslex.aproselection.core.network.clients.auth.model.toStorage
import io.ktor.client.call.body
import io.ktor.client.request.get
import io.ktor.client.request.post
import io.ktor.client.request.setBody
import io.ktor.http.appendPathSegments
import io.ktor.http.path
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flow
Expand All @@ -36,7 +33,7 @@ class AuthNetworkClientImpl(
networkClient
.apiClient
.post {
url.appendPathSegments("passport/registration")
url.path("passport/registration")
setBody<UserAuthRequestModel>(user)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,5 @@ data class UserAuthRequestModel(
@SerialName("username")
val username: String,
@SerialName("password")
val password: String
val password: String,
)
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package com.stslex.aproselection.core.ui.base

import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.stslex.aproselection.core.core.Logger
import com.stslex.aproselection.core.ui.base.store.Store
import com.stslex.aproselection.core.ui.base.store.Store.Action
import com.stslex.aproselection.core.ui.base.store.Store.Event
Expand All @@ -24,8 +23,4 @@ open class BaseViewModel<out S : State, out E : Event, in A : Action>(
fun sendAction(action: A) {
store.processAction(action)
}

fun handleError(throwable: Throwable) {
Logger.exception(throwable)
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.stslex.aproselection.core.ui.base.store

import com.stslex.aproselection.core.core.Logger
import com.stslex.aproselection.core.ui.base.store.Store.Action
import com.stslex.aproselection.core.ui.base.store.Store.Event
import com.stslex.aproselection.core.ui.base.store.Store.State
Expand Down Expand Up @@ -34,4 +35,8 @@ abstract class BaseStoreImpl<S : State, E : Event, A : Action> :
override fun init(scope: CoroutineScope) {
_scope = scope
}

fun logError(error: Throwable) {
Logger.exception(error)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import com.stslex.aproselection.feature.auth.data.repository.AuthRepositoryImpl
import com.stslex.aproselection.feature.auth.domain.interactor.AuthInteractor
import com.stslex.aproselection.feature.auth.domain.interactor.AuthInteractorImpl
import com.stslex.aproselection.feature.auth.ui.AuthViewModel
import com.stslex.aproselection.feature.auth.ui.store.AuthStore
import com.stslex.aproselection.feature.auth.ui.store.AuthStoreImpl
import org.koin.androidx.viewmodel.dsl.viewModelOf
import org.koin.core.module.dsl.bind
import org.koin.core.module.dsl.factoryOf
Expand All @@ -14,6 +16,7 @@ object ModuleFeatureAuth {

val moduleFeatureAuth = module {
viewModelOf(::AuthViewModel)
factoryOf(::AuthStoreImpl) { bind<AuthStore>() }
factoryOf(::AuthInteractorImpl) { bind<AuthInteractor>() }
factoryOf(::AuthRepositoryImpl) { bind<AuthRepository>() }
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.SnackbarHost
import androidx.compose.material3.SnackbarHostState
import androidx.compose.material3.Text
import androidx.compose.material3.TextField
import androidx.compose.runtime.Composable
Expand All @@ -28,14 +29,11 @@ import com.stslex.aproselection.feature.auth.R
import com.stslex.aproselection.feature.auth.ui.components.AuthBottomText
import com.stslex.aproselection.feature.auth.ui.components.AuthFieldsColumn
import com.stslex.aproselection.feature.auth.ui.components.AuthTitle
import com.stslex.aproselection.feature.auth.ui.model.ScreenLoadingState
import com.stslex.aproselection.feature.auth.ui.model.SnackbarActionType
import com.stslex.aproselection.feature.auth.ui.model.mvi.ScreenState
import com.stslex.aproselection.feature.auth.ui.model.screen.AuthScreenState
import com.stslex.aproselection.feature.auth.ui.model.screen.rememberAuthScreenState
import com.stslex.aproselection.feature.auth.ui.model.screen.text_field.UsernameTextFieldState
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow
import com.stslex.aproselection.feature.auth.ui.store.AuthStore

@SuppressLint("CoroutineCreationDuringComposition")
@Composable
Expand All @@ -61,7 +59,7 @@ fun AuthScreen(
}
}
}
if (state.screenLoadingState == ScreenLoadingState.Loading) {
if (state.screenLoadingState == AuthStore.ScreenLoadingState.Loading) {
Box(
modifier = Modifier
.fillMaxSize()
Expand Down Expand Up @@ -140,8 +138,14 @@ fun AuthScreenPreview() {
AppTheme {
AuthScreen(
state = rememberAuthScreenState(
screenStateFlow = { MutableStateFlow(ScreenState()) },
screenEventFlow = { MutableSharedFlow() },
screenState = AuthStore.State(
screenLoadingState = AuthStore.ScreenLoadingState.Content,
username = "",
password = "",
passwordSubmit = "",
authFieldsState = AuthStore.AuthFieldsState.AUTH
),
snackbarHostState = SnackbarHostState(),
processAction = {}
)
)
Expand Down
Loading

0 comments on commit 743af97

Please sign in to comment.