added init logic, updated userDTO, added change rights logic in admin panel, some fixes
This commit is contained in:
parent
952a1f6714
commit
6a78060f25
@ -4,6 +4,7 @@ import android.app.Application
|
||||
import com.displaynone.acss.components.acs.models.gate.GateServiceST
|
||||
import com.displaynone.acss.components.acs.models.visit.VisitServiceST
|
||||
import com.displaynone.acss.components.auth.models.user.UserServiceST
|
||||
import com.displaynone.acss.components.init.models.InitServiceST
|
||||
|
||||
class ACSSApplication : Application() {
|
||||
override fun onCreate() {
|
||||
@ -11,5 +12,6 @@ class ACSSApplication : Application() {
|
||||
UserServiceST.createInstance(this)
|
||||
GateServiceST.createInstance()
|
||||
VisitServiceST.createInstance()
|
||||
InitServiceST.createInstance()
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ import android.view.ViewGroup
|
||||
import androidx.paging.PagingDataAdapter
|
||||
import androidx.recyclerview.widget.DiffUtil
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.displaynone.acss.R
|
||||
import com.displaynone.acss.components.acs.models.visit.repository.dto.VisitDto
|
||||
import com.displaynone.acss.databinding.ItemScannerViewBinding
|
||||
|
||||
@ -37,7 +38,7 @@ class VisitAdapter: PagingDataAdapter<VisitDto, VisitAdapter.ViewHolder>(VisitDi
|
||||
): RecyclerView.ViewHolder(binding.root) {
|
||||
fun bind(item: VisitDto){
|
||||
binding.scanTime.text = item.createdAt
|
||||
binding.scannerId.text = item.gateId.toString()
|
||||
binding.scannerId.text = "Id " + item.gateId.toString()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -23,6 +23,7 @@ class UserMapper {
|
||||
photo = userEntity.photo,
|
||||
position = userEntity.position,
|
||||
roles = emptyList(),
|
||||
isACSBlocked = false
|
||||
// lastVisit = userEntity.lastVisit,
|
||||
)
|
||||
return userDto
|
||||
|
@ -70,6 +70,9 @@ class UserServiceST(
|
||||
fun logout(){
|
||||
tokenManager.clear()
|
||||
}
|
||||
suspend fun changeRights(login: String, isACSBlocked: Boolean): Result<Unit> {
|
||||
return userRepository.changeRightsByLogin(login, tokenManager.authTokenPair!!.accessToken, isACSBlocked)
|
||||
}
|
||||
suspend fun getInfo(): Result<UserDTO>{
|
||||
if (!tokenManager.hasTokens()) {
|
||||
throw RuntimeException("access token is null")
|
||||
|
@ -5,11 +5,13 @@ import com.displaynone.acss.components.auth.models.AuthTokenPair
|
||||
import com.displaynone.acss.config.Constants.serverUrl
|
||||
import com.displaynone.acss.config.Network
|
||||
import com.displaynone.acss.components.auth.models.user.repository.dto.RegisterUserDto
|
||||
import com.displaynone.acss.components.auth.models.user.repository.dto.UpdateUserDTO
|
||||
import com.displaynone.acss.components.auth.models.user.repository.dto.UserDTO
|
||||
import com.displaynone.acss.components.auth.models.user.repository.dto.UserLoginDto
|
||||
import io.ktor.client.call.body
|
||||
import io.ktor.client.request.get
|
||||
import io.ktor.client.request.headers
|
||||
import io.ktor.client.request.patch
|
||||
import io.ktor.client.request.post
|
||||
import io.ktor.client.request.setBody
|
||||
import io.ktor.client.statement.bodyAsText
|
||||
@ -101,25 +103,28 @@ class UserRepository(
|
||||
result.body()
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun register(login: String, password: String): Result<Unit> =
|
||||
withContext(Dispatchers.IO) {
|
||||
runCatching {
|
||||
val result = Network.client.post("$serverUrl/api/person/register") {
|
||||
contentType(ContentType.Application.Json)
|
||||
setBody(
|
||||
RegisterUserDto(
|
||||
login = login,
|
||||
password = password,
|
||||
)
|
||||
)
|
||||
suspend fun changeRightsByLogin(login: String, token: String, isACSBlocked: Boolean): Result<Unit> = withContext(Dispatchers.IO) {
|
||||
runCatching {
|
||||
val encodedLogin = login.encodeURLPath()
|
||||
val result = Network.client.patch("$serverUrl/api/users/login/$encodedLogin") {
|
||||
headers{
|
||||
append(HttpHeaders.Authorization, "Bearer $token")
|
||||
}
|
||||
if (result.status != HttpStatusCode.Created) {
|
||||
Log.w("UserRepository", "Status: ${result.status}, Body: ${result.body<String>()}")
|
||||
error("Status ${result.status}: ${result.body<String>()}")
|
||||
}
|
||||
Unit
|
||||
contentType(ContentType.Application.Json)
|
||||
setBody(UpdateUserDTO(
|
||||
password = null,
|
||||
name = null,
|
||||
photo = null,
|
||||
position = null,
|
||||
isACSBlocked = isACSBlocked
|
||||
))
|
||||
}
|
||||
if (result.status != HttpStatusCode.OK) {
|
||||
Log.w("UserRepository", "Status: ${result.status}, Body: ${result.body<String>()}")
|
||||
error("Status ${result.status}: ${result.body<String>()}")
|
||||
}
|
||||
Unit
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
package com.displaynone.acss.components.auth.models.user.repository.dto
|
||||
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data class UpdateUserDTO (
|
||||
@SerialName("password")
|
||||
val password: String?,
|
||||
@SerialName("name")
|
||||
val name: String?,
|
||||
@SerialName("photo")
|
||||
val photo: String?,
|
||||
@SerialName("position")
|
||||
val position: String?,
|
||||
@SerialName("isACSBlocked")
|
||||
val isACSBlocked: Boolean,
|
||||
)
|
@ -22,7 +22,8 @@ data class UserDTO (
|
||||
val position: String,
|
||||
@SerialName("roles")
|
||||
val roles: List<AuthorityDTO>,
|
||||
|
||||
@SerialName("acsblocked")
|
||||
val isACSBlocked: Boolean
|
||||
// @SerialName("lastVisit")
|
||||
// val lastVisit: String,
|
||||
) : java.io.Serializable
|
@ -0,0 +1,25 @@
|
||||
package com.displaynone.acss.components.init.models
|
||||
|
||||
import com.displaynone.acss.components.acs.models.visit.VisitServiceST
|
||||
import com.displaynone.acss.components.auth.models.user.UserServiceST
|
||||
import com.displaynone.acss.components.init.models.repository.InitRepository
|
||||
|
||||
class InitServiceST {
|
||||
private val initRepository = InitRepository()
|
||||
companion object {
|
||||
private var instance: InitServiceST? = null
|
||||
|
||||
fun createInstance() {
|
||||
if (instance == null) {
|
||||
instance = InitServiceST()
|
||||
}
|
||||
}
|
||||
|
||||
fun getInstance(): InitServiceST {
|
||||
return instance ?: throw RuntimeException("null instance")
|
||||
}
|
||||
}
|
||||
suspend fun ping(): Result<Boolean> {
|
||||
return initRepository.ping(UserServiceST.getInstance().getTokenPair().accessToken)
|
||||
}
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
package com.displaynone.acss.components.init.models.repository
|
||||
|
||||
import android.util.Log
|
||||
import com.displaynone.acss.components.auth.models.user.repository.dto.UserDTO
|
||||
import com.displaynone.acss.config.Constants.serverUrl
|
||||
import com.displaynone.acss.config.Network
|
||||
import io.ktor.client.call.body
|
||||
import io.ktor.client.request.get
|
||||
import io.ktor.client.request.headers
|
||||
import io.ktor.client.request.setBody
|
||||
import io.ktor.client.statement.bodyAsText
|
||||
import io.ktor.http.HttpHeaders
|
||||
import io.ktor.http.HttpStatusCode
|
||||
import io.ktor.http.encodeURLPath
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
class InitRepository {
|
||||
suspend fun ping(token: String): Result<Boolean> = withContext(
|
||||
Dispatchers.IO){
|
||||
runCatching {
|
||||
val result = Network.client.get("$serverUrl/api/utils/ping") {
|
||||
headers {
|
||||
append(HttpHeaders.Authorization, "Bearer $token")
|
||||
}
|
||||
}
|
||||
|
||||
result.status == HttpStatusCode.OK
|
||||
}
|
||||
}
|
||||
}
|
@ -1,22 +0,0 @@
|
||||
package com.displaynone.acss.components.main.utils
|
||||
|
||||
import com.displaynone.acss.config.Constants.serverUrl
|
||||
import com.displaynone.acss.config.Network
|
||||
import io.ktor.client.request.get
|
||||
import io.ktor.client.request.headers
|
||||
import io.ktor.http.HttpHeaders
|
||||
import io.ktor.http.HttpStatusCode
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
suspend fun pingServer(token: String): Result<Boolean> = withContext(Dispatchers.IO) {
|
||||
runCatching {
|
||||
val result = Network.client.get("$serverUrl/api/ping") {
|
||||
headers {
|
||||
append(HttpHeaders.Authorization, "Bearer $token")
|
||||
}
|
||||
}
|
||||
|
||||
result.status == HttpStatusCode.OK
|
||||
}
|
||||
}
|
@ -7,18 +7,23 @@ import android.os.Bundle
|
||||
import android.util.Log
|
||||
import android.view.View
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.viewModels
|
||||
import androidx.navigation.NavController
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import com.displaynone.acss.R
|
||||
import com.displaynone.acss.components.auth.models.user.UserServiceST
|
||||
import com.displaynone.acss.components.auth.models.user.repository.dto.UserDTO
|
||||
import com.displaynone.acss.databinding.FragmentInitBinding
|
||||
import com.displaynone.acss.util.collectWithLifecycle
|
||||
import com.displaynone.acss.util.navigateTo
|
||||
|
||||
class InitFragment : Fragment(R.layout.fragment_init) {
|
||||
private var _binding: FragmentInitBinding? = null
|
||||
private val binding: FragmentInitBinding get() = _binding!!
|
||||
|
||||
private val viewModel: InitFragmentViewModel by viewModels()
|
||||
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
_binding = FragmentInitBinding.bind(view)
|
||||
@ -28,33 +33,43 @@ class InitFragment : Fragment(R.layout.fragment_init) {
|
||||
return
|
||||
}
|
||||
|
||||
if (!pingServer()) {
|
||||
handleError(R.string.serverIsUnabailable)
|
||||
return
|
||||
}
|
||||
pingServer()
|
||||
|
||||
val navController: NavController = findNavController()
|
||||
|
||||
if (!isUserAuthenticated()) {
|
||||
navigateTo(navController, R.id.action_nav_init_to_nav_auth)
|
||||
return
|
||||
}
|
||||
|
||||
val user: UserDTO? = updateUser()
|
||||
if (user == null) {
|
||||
navigateTo(navController, R.id.action_nav_init_to_nav_auth)
|
||||
return
|
||||
}
|
||||
|
||||
navigateTo(navController, R.id.action_nav_init_to_nav_profile)
|
||||
}
|
||||
|
||||
private fun pingServer(): Boolean {
|
||||
return true
|
||||
private fun pingServer() {
|
||||
viewModel.pingServer()
|
||||
viewModel.state.collectWithLifecycle(this) { state ->
|
||||
if (state is InitFragmentViewModel.State.Show){
|
||||
if(!state.item){
|
||||
handleError(R.string.serverIsUnabailable)
|
||||
} else{
|
||||
val navController: NavController = findNavController()
|
||||
|
||||
if (!isUserAuthenticated()) {
|
||||
navigateTo(navController, R.id.action_nav_init_to_nav_auth)
|
||||
} else {
|
||||
updateUser(navController)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateUser(): UserDTO? {
|
||||
return null
|
||||
private fun updateUser(navController: NavController) {
|
||||
viewModel.updateUserInfo()
|
||||
viewModel.state.collectWithLifecycle(this){ state ->
|
||||
if (state is InitFragmentViewModel.State.Update) {
|
||||
if (state.item == null) {
|
||||
navigateTo(navController, R.id.action_nav_init_to_nav_auth)
|
||||
} else{
|
||||
navigateTo(navController, R.id.action_nav_init_to_nav_profile)
|
||||
}
|
||||
}
|
||||
if (state is InitFragmentViewModel.State.Error){
|
||||
navigateTo(navController, R.id.action_nav_init_to_nav_auth)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkInternetConnection(): Boolean {
|
||||
@ -91,4 +106,7 @@ class InitFragment : Fragment(R.layout.fragment_init) {
|
||||
private fun handleError(string: Int) {
|
||||
binding.error.text = requireContext().getString(string)
|
||||
}
|
||||
private fun handleError(errorMessage: String) {
|
||||
binding.error.text = errorMessage
|
||||
}
|
||||
}
|
@ -1,14 +1,53 @@
|
||||
package com.displaynone.acss.ui.init
|
||||
|
||||
import android.util.Log
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.displaynone.acss.components.auth.models.user.UserServiceST
|
||||
import com.displaynone.acss.components.auth.models.user.repository.dto.UserDTO
|
||||
import com.displaynone.acss.components.init.models.InitServiceST
|
||||
import com.displaynone.acss.ui.profile.ProfileViewModel.State
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.asStateFlow
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
class InitFragmentViewModel: ViewModel() {
|
||||
private fun pingServer(): Boolean {
|
||||
|
||||
val _state = MutableStateFlow<State>(State.Loading)
|
||||
val state = _state.asStateFlow()
|
||||
fun pingServer() {
|
||||
viewModelScope.launch {
|
||||
InitServiceST.getInstance().ping().fold(
|
||||
onSuccess = { _state.emit(State.Show(true)) },
|
||||
onFailure = {
|
||||
_state.emit(State.Show(false))
|
||||
Log.d("InitFragmentViewModel", "failed to ping") }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateUser(): UserDTO? {
|
||||
|
||||
fun updateUserInfo() {
|
||||
viewModelScope.launch {
|
||||
UserServiceST.getInstance().getInfo().fold(
|
||||
onSuccess = { data ->
|
||||
_state.emit(State.Update(data))
|
||||
},
|
||||
onFailure = { error ->
|
||||
_state.emit(State.Error(error.message.toString()))
|
||||
Log.d("InitFragmentViewModel", "failed to update user info ${error.message}")
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
sealed interface State {
|
||||
data object Loading : State
|
||||
data class Show(
|
||||
val item: Boolean
|
||||
) : State
|
||||
data class Update(
|
||||
val item: UserDTO
|
||||
) : State
|
||||
data class Error(
|
||||
val errorMessage: String
|
||||
) : State
|
||||
}
|
||||
}
|
@ -57,6 +57,7 @@ class ProfileFragment: Fragment(R.layout.fragment_profile) {
|
||||
waitForQRScanResult()
|
||||
} else{
|
||||
showData(getUserDto()!!)
|
||||
|
||||
Log.d("ProfileFragment", "set login")
|
||||
viewModel.visitListStateFromLogin.collectWithLifecycle(this) { data ->
|
||||
adapter.submitData(data)
|
||||
@ -92,6 +93,7 @@ class ProfileFragment: Fragment(R.layout.fragment_profile) {
|
||||
binding.logout.visibility = View.GONE
|
||||
binding.scan.visibility = View.GONE
|
||||
binding.buttonSearch.visibility = View.GONE
|
||||
binding.changeRights.visibility = View.VISIBLE
|
||||
}
|
||||
fun showMyData(userDTO: UserDTO){
|
||||
binding.fio.text = userDTO.name
|
||||
@ -101,7 +103,11 @@ class ProfileFragment: Fragment(R.layout.fragment_profile) {
|
||||
fun showData(userDTO: UserDTO){
|
||||
binding.fio.text = userDTO.name
|
||||
binding.position.text = userDTO.position
|
||||
binding.changeRights.text = if(userDTO.isACSBlocked) "Разблокировать пользователя" else "Заблокировать пользователя"
|
||||
viewModel.setLogin(login1 = userDTO.login)
|
||||
binding.changeRights.setOnClickListener {
|
||||
viewModel.changeRights(userDTO.login, !userDTO.isACSBlocked)
|
||||
}
|
||||
Log.d("ProfileFragment", userDTO.login)
|
||||
|
||||
// binding.lastEntry.text = userDTO.lastVisit
|
||||
|
@ -10,6 +10,7 @@ import com.displaynone.acss.components.auth.models.user.UserServiceST
|
||||
import com.displaynone.acss.components.acs.models.visit.VisitListPagingSource
|
||||
import com.displaynone.acss.components.acs.models.visit.VisitServiceST
|
||||
import com.displaynone.acss.components.auth.models.user.repository.dto.UserDTO
|
||||
import io.ktor.util.reflect.instanceOf
|
||||
import kotlinx.coroutines.channels.BufferOverflow
|
||||
import kotlinx.coroutines.channels.Channel
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
@ -66,6 +67,19 @@ class ProfileViewModel(): ViewModel() {
|
||||
)
|
||||
}
|
||||
}
|
||||
fun changeRights(login: String, isACSBlocked: Boolean){
|
||||
viewModelScope.launch {
|
||||
UserServiceST.getInstance().changeRights(login, isACSBlocked).fold(
|
||||
onSuccess = {
|
||||
Log.d("ProfileViewModel", "changed rights")
|
||||
// _state.emit(State.Change(isACSBlocked))
|
||||
},
|
||||
onFailure = { error ->
|
||||
Log.d("ProfileViewModel", "failed to change rights ${error.message}")
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
fun openAuth(){
|
||||
viewModelScope.launch {
|
||||
_action.send(Action.GoToAuth)
|
||||
@ -82,6 +96,9 @@ class ProfileViewModel(): ViewModel() {
|
||||
data class Show(
|
||||
val item: UserDTO
|
||||
) : State
|
||||
data class Change(
|
||||
val item: Boolean
|
||||
)
|
||||
}
|
||||
sealed interface Action {
|
||||
data object GoToAuth: Action
|
||||
|
Loading…
x
Reference in New Issue
Block a user