From f9d31d4743f33bba6d3a71cd873bb5d0064d06d6 Mon Sep 17 00:00:00 2001 From: Nymos Date: Wed, 19 Feb 2025 16:23:18 +0300 Subject: [PATCH] Implement logout on token/credentials corruption --- .../com/nto/data/repository/DataRepository.kt | 2 +- .../nto/data/repository/DataRepositoryImpl.kt | 5 +++++ .../main/java/com/nto/data/utils/Provider.kt | 2 +- .../nto/domain/repository/DomainRepository.kt | 1 + .../domain/repository/DomainRepositoryImpl.kt | 8 +++++-- .../com/nto/domain/usecase/ProfileUseCase.kt | 3 +++ .../java/com/nto/presentation/MainActivity.kt | 1 + .../nto/presentation/composable/Navigation.kt | 2 +- .../screens/profileScreen/ProfileScreen.kt | 4 ++-- .../screens/profileScreen/ProfileState.kt | 3 ++- .../screens/profileScreen/ProfileViewModel.kt | 21 ++++++++++++++----- 11 files changed, 39 insertions(+), 13 deletions(-) diff --git a/data/src/main/java/com/nto/data/repository/DataRepository.kt b/data/src/main/java/com/nto/data/repository/DataRepository.kt index 2501ba9..aecbf0e 100644 --- a/data/src/main/java/com/nto/data/repository/DataRepository.kt +++ b/data/src/main/java/com/nto/data/repository/DataRepository.kt @@ -3,7 +3,6 @@ package com.nto.data.repository import com.nto.data.models.LoginResult import com.nto.data.models.ScanResult import com.nto.data.models.UserDTO -import com.nto.data.models.cards.VisitCardDTO import com.nto.data.models.cards.VisitCardWrapper interface DataRepository { @@ -14,4 +13,5 @@ interface DataRepository { suspend fun getInfo(): UserDTO suspend fun getVisits(id: String?): VisitCardWrapper suspend fun open(): ScanResult + suspend fun logout() } \ No newline at end of file diff --git a/data/src/main/java/com/nto/data/repository/DataRepositoryImpl.kt b/data/src/main/java/com/nto/data/repository/DataRepositoryImpl.kt index a1dfb16..b452c10 100644 --- a/data/src/main/java/com/nto/data/repository/DataRepositoryImpl.kt +++ b/data/src/main/java/com/nto/data/repository/DataRepositoryImpl.kt @@ -2,6 +2,7 @@ package com.nto.data.repository import android.content.Context import android.content.Context.MODE_PRIVATE +import android.content.SharedPreferences import com.nto.data.models.LoginResult import com.nto.data.models.ScanResult import com.nto.data.models.UserDTO @@ -59,4 +60,8 @@ class DataRepositoryImpl @Inject constructor(@ApplicationContext private val con } } + override suspend fun logout() { + context.getSharedPreferences("auth", MODE_PRIVATE).edit().remove("token").remove("login").apply() + } + } \ No newline at end of file diff --git a/data/src/main/java/com/nto/data/utils/Provider.kt b/data/src/main/java/com/nto/data/utils/Provider.kt index 277ef7f..60a6666 100644 --- a/data/src/main/java/com/nto/data/utils/Provider.kt +++ b/data/src/main/java/com/nto/data/utils/Provider.kt @@ -15,7 +15,7 @@ object Provider { @Singleton fun provideRetrofit(): RetrofitApi { return Retrofit.Builder() - .baseUrl("https://test.com/") + .baseUrl("http://v-chat.ru/") .addConverterFactory(GsonConverterFactory.create()) .build().create(RetrofitApi::class.java) } diff --git a/domain/src/main/java/com/nto/domain/repository/DomainRepository.kt b/domain/src/main/java/com/nto/domain/repository/DomainRepository.kt index d594e9d..eef47be 100644 --- a/domain/src/main/java/com/nto/domain/repository/DomainRepository.kt +++ b/domain/src/main/java/com/nto/domain/repository/DomainRepository.kt @@ -12,4 +12,5 @@ interface DomainRepository { suspend fun getInfo(): UserDTO suspend fun getVisits(id: String): VisitCardWrapper suspend fun open(): ScanResult + suspend fun logout() } \ No newline at end of file diff --git a/domain/src/main/java/com/nto/domain/repository/DomainRepositoryImpl.kt b/domain/src/main/java/com/nto/domain/repository/DomainRepositoryImpl.kt index 407b71a..2ffc362 100644 --- a/domain/src/main/java/com/nto/domain/repository/DomainRepositoryImpl.kt +++ b/domain/src/main/java/com/nto/domain/repository/DomainRepositoryImpl.kt @@ -36,7 +36,7 @@ class DomainRepositoryImpl @Inject constructor(private val dataRepositoryImpl: D return try { return dataRepositoryImpl.getInfo() } catch (e: IOException) { - UserDTO(isError = true) + UserDTO(isError = true, isUnauthorized = true) //TODO } } @@ -44,7 +44,7 @@ class DomainRepositoryImpl @Inject constructor(private val dataRepositoryImpl: D return try { dataRepositoryImpl.getVisits(id) } catch (e: IOException) { - VisitCardWrapper(null, isUnauthorized = true) + VisitCardWrapper(null, isUnauthorized = true) //TODO } } @@ -52,4 +52,8 @@ class DomainRepositoryImpl @Inject constructor(private val dataRepositoryImpl: D return dataRepositoryImpl.open() } + override suspend fun logout() { + dataRepositoryImpl.logout() + } + } \ No newline at end of file diff --git a/domain/src/main/java/com/nto/domain/usecase/ProfileUseCase.kt b/domain/src/main/java/com/nto/domain/usecase/ProfileUseCase.kt index fc80b51..62cdf1b 100644 --- a/domain/src/main/java/com/nto/domain/usecase/ProfileUseCase.kt +++ b/domain/src/main/java/com/nto/domain/usecase/ProfileUseCase.kt @@ -8,4 +8,7 @@ class ProfileUseCase @Inject constructor(private val domainRepositoryImpl: Domai suspend fun getInfo(): UserDTO{ return domainRepositoryImpl.getInfo() } + suspend fun logout(){ + return domainRepositoryImpl.logout() + } } \ No newline at end of file diff --git a/presentation/src/main/java/com/nto/presentation/MainActivity.kt b/presentation/src/main/java/com/nto/presentation/MainActivity.kt index 19c82bc..7c14f27 100644 --- a/presentation/src/main/java/com/nto/presentation/MainActivity.kt +++ b/presentation/src/main/java/com/nto/presentation/MainActivity.kt @@ -10,6 +10,7 @@ import androidx.activity.compose.setContent import androidx.activity.enableEdgeToEdge import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding +import androidx.compose.material3.OutlinedButton import androidx.compose.material3.Scaffold import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.toArgb diff --git a/presentation/src/main/java/com/nto/presentation/composable/Navigation.kt b/presentation/src/main/java/com/nto/presentation/composable/Navigation.kt index 58fbed4..1bbb8f3 100644 --- a/presentation/src/main/java/com/nto/presentation/composable/Navigation.kt +++ b/presentation/src/main/java/com/nto/presentation/composable/Navigation.kt @@ -15,7 +15,7 @@ fun Navigation(navController: NavHostController, modifier: Modifier = Modifier) NavHost( navController = navController, modifier = modifier, - startDestination = Destinations.Profile + startDestination = Destinations.Login ) { composable { LoginScreen(navController) diff --git a/presentation/src/main/java/com/nto/presentation/screens/profileScreen/ProfileScreen.kt b/presentation/src/main/java/com/nto/presentation/screens/profileScreen/ProfileScreen.kt index ec787b0..de8db8b 100644 --- a/presentation/src/main/java/com/nto/presentation/screens/profileScreen/ProfileScreen.kt +++ b/presentation/src/main/java/com/nto/presentation/screens/profileScreen/ProfileScreen.kt @@ -70,9 +70,9 @@ fun ProfileScreen( scanOptions.setOrientationLocked(false) scanOptions.setCaptureActivity(CustomCaptureActivity::class.java) - LaunchedEffect(Unit) { + LaunchedEffect(state.isUnauthorized) { if (state.isUnauthorized) { - navController.navigate(Destinations.Login) + viewModel.logout(navController) } } diff --git a/presentation/src/main/java/com/nto/presentation/screens/profileScreen/ProfileState.kt b/presentation/src/main/java/com/nto/presentation/screens/profileScreen/ProfileState.kt index b4bafbd..9fe77c9 100644 --- a/presentation/src/main/java/com/nto/presentation/screens/profileScreen/ProfileState.kt +++ b/presentation/src/main/java/com/nto/presentation/screens/profileScreen/ProfileState.kt @@ -18,10 +18,11 @@ data class ProfileState( val visits: List = listOf() ){ fun deserialize(o: UserDTO, context: Context){ + val dateFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss") this.firstName = o.firstName this.secondName = o.secondName this.thirdName = o.thirdName - this.lastOpen = SimpleDateFormat.getDateInstance().format(o.lastVisit) + this.lastOpen = o.lastVisit.format(dateFormat) this.job = translatePosition(o.position, context) this.isUnauthorized = o.isUnauthorized } diff --git a/presentation/src/main/java/com/nto/presentation/screens/profileScreen/ProfileViewModel.kt b/presentation/src/main/java/com/nto/presentation/screens/profileScreen/ProfileViewModel.kt index b122518..fa739f8 100644 --- a/presentation/src/main/java/com/nto/presentation/screens/profileScreen/ProfileViewModel.kt +++ b/presentation/src/main/java/com/nto/presentation/screens/profileScreen/ProfileViewModel.kt @@ -4,19 +4,18 @@ import android.content.Context import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import androidx.navigation.NavController -import com.nto.data.models.Position import com.nto.data.models.QRDTO import com.nto.data.models.cards.VisitCardDTO import com.nto.data.models.cards.VisitType import com.nto.data.utils.Destinations import com.nto.domain.usecase.ProfileUseCase -import com.nto.presentation.R import dagger.hilt.android.lifecycle.HiltViewModel import dagger.hilt.android.qualifiers.ApplicationContext import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.invoke import kotlinx.coroutines.launch import java.time.LocalDateTime import javax.inject.Inject @@ -32,7 +31,15 @@ class ProfileViewModel @Inject constructor( "Алексеевич", "20 января 2024 20:21", "Senior UI/UX designer", - visits = listOf(VisitCardDTO("Кабинет 207", 10020, LocalDateTime.now(), VisitType.CARD_ENTRY, qrCode = QRDTO(12032, "Кобинет 52"))) + visits = listOf( + VisitCardDTO( + "Кабинет 207", + 10020, + LocalDateTime.now(), + VisitType.CARD_ENTRY, + qrCode = QRDTO(12032, "Кобинет 52") + ) + ) ) ) @@ -42,7 +49,6 @@ class ProfileViewModel @Inject constructor( fun updateInfo() { viewModelScope.launch(Dispatchers.IO) { val result = useCase.getInfo() - if (result.isError) return@launch _state.tryEmit(ProfileState().apply { deserialize(result, context) }) } } @@ -52,7 +58,12 @@ class ProfileViewModel @Inject constructor( } fun logout(navController: NavController) { - //TODO + viewModelScope.launch(Dispatchers.IO) { + useCase.logout() + Dispatchers.Main { + navController.navigate(Destinations.Login) + } + } } fun option(navController: NavController) {