Implement logout on token/credentials corruption

This commit is contained in:
Nymos 2025-02-19 16:23:18 +03:00
parent f41e8c734d
commit f9d31d4743
11 changed files with 39 additions and 13 deletions

View File

@ -3,7 +3,6 @@ package com.nto.data.repository
import com.nto.data.models.LoginResult import com.nto.data.models.LoginResult
import com.nto.data.models.ScanResult import com.nto.data.models.ScanResult
import com.nto.data.models.UserDTO import com.nto.data.models.UserDTO
import com.nto.data.models.cards.VisitCardDTO
import com.nto.data.models.cards.VisitCardWrapper import com.nto.data.models.cards.VisitCardWrapper
interface DataRepository { interface DataRepository {
@ -14,4 +13,5 @@ interface DataRepository {
suspend fun getInfo(): UserDTO suspend fun getInfo(): UserDTO
suspend fun getVisits(id: String?): VisitCardWrapper suspend fun getVisits(id: String?): VisitCardWrapper
suspend fun open(): ScanResult suspend fun open(): ScanResult
suspend fun logout()
} }

View File

@ -2,6 +2,7 @@ package com.nto.data.repository
import android.content.Context import android.content.Context
import android.content.Context.MODE_PRIVATE import android.content.Context.MODE_PRIVATE
import android.content.SharedPreferences
import com.nto.data.models.LoginResult import com.nto.data.models.LoginResult
import com.nto.data.models.ScanResult import com.nto.data.models.ScanResult
import com.nto.data.models.UserDTO 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()
}
} }

View File

@ -15,7 +15,7 @@ object Provider {
@Singleton @Singleton
fun provideRetrofit(): RetrofitApi { fun provideRetrofit(): RetrofitApi {
return Retrofit.Builder() return Retrofit.Builder()
.baseUrl("https://test.com/") .baseUrl("http://v-chat.ru/")
.addConverterFactory(GsonConverterFactory.create()) .addConverterFactory(GsonConverterFactory.create())
.build().create(RetrofitApi::class.java) .build().create(RetrofitApi::class.java)
} }

View File

@ -12,4 +12,5 @@ interface DomainRepository {
suspend fun getInfo(): UserDTO suspend fun getInfo(): UserDTO
suspend fun getVisits(id: String): VisitCardWrapper suspend fun getVisits(id: String): VisitCardWrapper
suspend fun open(): ScanResult suspend fun open(): ScanResult
suspend fun logout()
} }

View File

@ -36,7 +36,7 @@ class DomainRepositoryImpl @Inject constructor(private val dataRepositoryImpl: D
return try { return try {
return dataRepositoryImpl.getInfo() return dataRepositoryImpl.getInfo()
} catch (e: IOException) { } 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 { return try {
dataRepositoryImpl.getVisits(id) dataRepositoryImpl.getVisits(id)
} catch (e: IOException) { } 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() return dataRepositoryImpl.open()
} }
override suspend fun logout() {
dataRepositoryImpl.logout()
}
} }

View File

@ -8,4 +8,7 @@ class ProfileUseCase @Inject constructor(private val domainRepositoryImpl: Domai
suspend fun getInfo(): UserDTO{ suspend fun getInfo(): UserDTO{
return domainRepositoryImpl.getInfo() return domainRepositoryImpl.getInfo()
} }
suspend fun logout(){
return domainRepositoryImpl.logout()
}
} }

View File

@ -10,6 +10,7 @@ import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge import androidx.activity.enableEdgeToEdge
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.material3.OutlinedButton
import androidx.compose.material3.Scaffold import androidx.compose.material3.Scaffold
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.toArgb import androidx.compose.ui.graphics.toArgb

View File

@ -15,7 +15,7 @@ fun Navigation(navController: NavHostController, modifier: Modifier = Modifier)
NavHost( NavHost(
navController = navController, navController = navController,
modifier = modifier, modifier = modifier,
startDestination = Destinations.Profile startDestination = Destinations.Login
) { ) {
composable<Destinations.Login> { composable<Destinations.Login> {
LoginScreen(navController) LoginScreen(navController)

View File

@ -70,9 +70,9 @@ fun ProfileScreen(
scanOptions.setOrientationLocked(false) scanOptions.setOrientationLocked(false)
scanOptions.setCaptureActivity(CustomCaptureActivity::class.java) scanOptions.setCaptureActivity(CustomCaptureActivity::class.java)
LaunchedEffect(Unit) { LaunchedEffect(state.isUnauthorized) {
if (state.isUnauthorized) { if (state.isUnauthorized) {
navController.navigate(Destinations.Login) viewModel.logout(navController)
} }
} }

View File

@ -18,10 +18,11 @@ data class ProfileState(
val visits: List<VisitCardDTO> = listOf() val visits: List<VisitCardDTO> = listOf()
){ ){
fun deserialize(o: UserDTO, context: Context){ fun deserialize(o: UserDTO, context: Context){
val dateFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")
this.firstName = o.firstName this.firstName = o.firstName
this.secondName = o.secondName this.secondName = o.secondName
this.thirdName = o.thirdName this.thirdName = o.thirdName
this.lastOpen = SimpleDateFormat.getDateInstance().format(o.lastVisit) this.lastOpen = o.lastVisit.format(dateFormat)
this.job = translatePosition(o.position, context) this.job = translatePosition(o.position, context)
this.isUnauthorized = o.isUnauthorized this.isUnauthorized = o.isUnauthorized
} }

View File

@ -4,19 +4,18 @@ import android.content.Context
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import androidx.navigation.NavController import androidx.navigation.NavController
import com.nto.data.models.Position
import com.nto.data.models.QRDTO import com.nto.data.models.QRDTO
import com.nto.data.models.cards.VisitCardDTO import com.nto.data.models.cards.VisitCardDTO
import com.nto.data.models.cards.VisitType import com.nto.data.models.cards.VisitType
import com.nto.data.utils.Destinations import com.nto.data.utils.Destinations
import com.nto.domain.usecase.ProfileUseCase import com.nto.domain.usecase.ProfileUseCase
import com.nto.presentation.R
import dagger.hilt.android.lifecycle.HiltViewModel import dagger.hilt.android.lifecycle.HiltViewModel
import dagger.hilt.android.qualifiers.ApplicationContext import dagger.hilt.android.qualifiers.ApplicationContext
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.invoke
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import java.time.LocalDateTime import java.time.LocalDateTime
import javax.inject.Inject import javax.inject.Inject
@ -32,7 +31,15 @@ class ProfileViewModel @Inject constructor(
"Алексеевич", "Алексеевич",
"20 января 2024 20:21", "20 января 2024 20:21",
"Senior UI/UX designer", "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() { fun updateInfo() {
viewModelScope.launch(Dispatchers.IO) { viewModelScope.launch(Dispatchers.IO) {
val result = useCase.getInfo() val result = useCase.getInfo()
if (result.isError) return@launch
_state.tryEmit(ProfileState().apply { deserialize(result, context) }) _state.tryEmit(ProfileState().apply { deserialize(result, context) })
} }
} }
@ -52,7 +58,12 @@ class ProfileViewModel @Inject constructor(
} }
fun logout(navController: NavController) { fun logout(navController: NavController) {
//TODO viewModelScope.launch(Dispatchers.IO) {
useCase.logout()
Dispatchers.Main {
navController.navigate(Destinations.Login)
}
}
} }
fun option(navController: NavController) { fun option(navController: NavController) {