day2_commit_13_back_to_Json

This commit is contained in:
Terebov_Maksim 2025-02-19 16:56:30 +03:00
parent 3da4b99cc0
commit 907c1c5d1c
6 changed files with 72 additions and 57 deletions

View File

@ -4,9 +4,9 @@ import dagger.Module
import dagger.Provides import dagger.Provides
import dagger.hilt.InstallIn import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent import dagger.hilt.components.SingletonComponent
import okhttp3.OkHttpClient
import retrofit2.Retrofit import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory import retrofit2.converter.gson.GsonConverterFactory
import ru.myitschool.work.api.ApiService
import ru.myitschool.work.core.Constants import ru.myitschool.work.core.Constants
import javax.inject.Singleton import javax.inject.Singleton
@ -16,9 +16,20 @@ object ApiModule {
@Provides @Provides
@Singleton @Singleton
fun provideRetrofit(): Retrofit { fun provideOkHttpClient(): OkHttpClient {
val username = "pivanov" // Замените на ваш логин
val password = "password123" // Замените на ваш пароль
return OkHttpClient.Builder()
.addInterceptor(AuthInterceptor(username, password))
.build()
}
@Provides
@Singleton
fun provideRetrofit(client: OkHttpClient): Retrofit {
return Retrofit.Builder() return Retrofit.Builder()
.baseUrl(Constants.SERVER_ADDRESS) .baseUrl(Constants.SERVER_ADDRESS)
.client(client)
.addConverterFactory(GsonConverterFactory.create()) .addConverterFactory(GsonConverterFactory.create())
.build() .build()
} }

View File

@ -6,14 +6,17 @@ import retrofit2.http.GET
import retrofit2.http.PATCH import retrofit2.http.PATCH
import retrofit2.http.POST import retrofit2.http.POST
import retrofit2.http.Path import retrofit2.http.Path
import retrofit2.http.Query
interface ApiService { interface ApiService {
// Метод для аутентификации // Метод для аутентификации
@POST("/api/auth") // Изменено на POST и путь к аутентификации @GET("/api/auth") // Используем GET для аутентификации
suspend fun authenticate( suspend fun authenticate(
@Body payload: AuthRequest // Передаем объект с логином и паролем @Query("login") login: String, // Передаем логин как параметр запроса
): Response<UserAuthResponse> // Возвращаем UserAuthResponse @Query("password") password: String // Передаем пароль как параметр запроса
): Response<UserAuthResponse> // Возвращаем JSON как объект UserAuthResponse
// Другие методы...
@GET("/api/{login}/info") // Получение информации о пользователе @GET("/api/{login}/info") // Получение информации о пользователе
suspend fun getUserInfo(@Path("login") login: String): Response<Map<String, Any>> suspend fun getUserInfo(@Path("login") login: String): Response<Map<String, Any>>
@ -30,12 +33,6 @@ interface ApiService {
suspend fun getAllWorkers(): Response<List<EmployeeData>> suspend fun getAllWorkers(): Response<List<EmployeeData>>
} }
// Модель данных для запроса аутентификации
data class AuthRequest(
val login: String,
val password: String // Поле для пароля
)
// Модель данных для ответа аутентификации // Модель данных для ответа аутентификации
data class UserAuthResponse( data class UserAuthResponse(
val role: String // Добавляем поле для роли val role: String // Добавляем поле для роли

View File

@ -0,0 +1,16 @@
package ru.myitschool.work.api
import okhttp3.Interceptor
import okhttp3.Response
import java.util.Base64
class AuthInterceptor(private val username: String, private val password: String) : Interceptor {
override fun intercept(chain: Interceptor.Chain): Response {
val originalRequest = chain.request()
val credential = Base64.getEncoder().encodeToString("$username:$password".toByteArray())
val newRequest = originalRequest.newBuilder()
.addHeader("Authorization", "Basic $credential")
.build()
return chain.proceed(newRequest)
}
}

View File

@ -1,5 +1,5 @@
package ru.myitschool.work.core package ru.myitschool.work.core
// БЕРИТЕ И ИЗМЕНЯЙТЕ ХОСТ ТОЛЬКО ЗДЕСЬ И НЕ БЕРИТЕ ИЗ ДРУГИХ МЕСТ. ФАЙЛ ПЕРЕМЕЩАТЬ НЕЛЬЗЯ // БЕРИТЕ И ИЗМЕНЯЙТЕ ХОСТ ТОЛЬКО ЗДЕСЬ И НЕ БЕРИТЕ ИЗ ДРУГИХ МЕСТ. ФАЙЛ ПЕРЕМЕЩАТЬ НЕЛЬЗЯ
object Constants { object Constants {
const val SERVER_ADDRESS = "const val SERVER_ADDRESS = \"http://localhost:8080\"\n" const val SERVER_ADDRESS = "http://192.168.1.131:8080"
} }

View File

@ -85,15 +85,12 @@ class LoginFragment : Fragment(R.layout.fragment_login) {
} }
private fun subscribe() { private fun subscribe() {
viewModel.state.collectWhenStarted(this) { state -> lifecycleScope.launch {
binding.loading.visibleOrGone(false) viewModel.state.collect { state ->
binding.loading.visibleOrGone(false)
try {
if (state.maintenance) { if (state.maintenance) {
showMaintenanceDialog() // Показываем диалог о техработах showMaintenanceDialog() // Показываем диалог о техработах
} else if (state.error != null) {
binding.error.text = state.error
binding.error.visibility = View.VISIBLE
} else if (state.success) { } else if (state.success) {
binding.error.visibility = View.GONE binding.error.visibility = View.GONE
authPreferences.saveLoginState(true) authPreferences.saveLoginState(true)
@ -106,11 +103,11 @@ class LoginFragment : Fragment(R.layout.fragment_login) {
} }
Toast.makeText(context, "Авторизация прошла успешно", Toast.LENGTH_SHORT).show() Toast.makeText(context, "Авторизация прошла успешно", Toast.LENGTH_SHORT).show()
navigateToMainScreen() navigateToMainScreen() // Перенаправление на следующий экран
} else if (state.error != null) {
binding.error.text = state.error
binding.error.visibility = View.VISIBLE
} }
} catch (e: Exception) {
Log.e("LoginFragment", "Ошибка при обработке состояния", e)
Toast.makeText(context, "Произошла ошибка. Пожалуйста, попробуйте снова.", Toast.LENGTH_SHORT).show()
} }
} }
} }
@ -119,7 +116,7 @@ class LoginFragment : Fragment(R.layout.fragment_login) {
AlertDialog.Builder(requireContext()) AlertDialog.Builder(requireContext())
.setTitle("Технические работы") .setTitle("Технические работы")
.setMessage("Проводятся техработы, пожалуйста, подождите.") .setMessage("Проводятся техработы, пожалуйста, подождите.")
.setPositiveButton("ОК") { dialog, _ -> dialog.dismiss() } .setPositiveButton("ОК ") { dialog, _ -> dialog.dismiss() }
.setCancelable(false) .setCancelable(false)
.show() .show()
} }

View File

@ -1,53 +1,46 @@
package ru.myitschool.work.ui.login package ru.myitschool.work.ui.login
import android.content.Context import android.util.Log
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel import dagger.hilt.android.lifecycle.HiltViewModel
import dagger.hilt.android.qualifiers.ApplicationContext
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import okhttp3.Credentials
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import ru.myitschool.work.SessionManager import ru.myitschool.work.SessionManager
import ru.myitschool.work.api.ApiService import ru.myitschool.work.api.ApiService
import ru.myitschool.work.api.AuthRequest
import ru.myitschool.work.api.UserAuthResponse import ru.myitschool.work.api.UserAuthResponse
import ru.myitschool.work.core.Constants
import javax.inject.Inject import javax.inject.Inject
@HiltViewModel @HiltViewModel
class LoginViewModel @Inject constructor( class LoginViewModel @Inject constructor(
@ApplicationContext private val context: Context, private val apiService: ApiService
) : ViewModel() { ) : ViewModel() {
private val _state = MutableStateFlow(LoginState())
val state = _state.asStateFlow()
private val apiService: ApiService by lazy { private val _state = MutableStateFlow(LoginState())
Retrofit.Builder() val state: StateFlow<LoginState> get() = _state
.baseUrl(Constants.SERVER_ADDRESS)
.addConverterFactory(GsonConverterFactory.create())
.build()
.create(ApiService::class.java)
}
fun authenticate(username: String, password: String) { fun authenticate(username: String, password: String) {
if (isValidUsername(username)) { if (isValidUsername(username)) {
viewModelScope.launch { viewModelScope.launch {
try { try {
val payload = AuthRequest(username, password) // Создаем объект запроса val response = apiService.authenticate(username, password)
val response = apiService.authenticate(payload) // Вызываем метод аутентификации Log.d("LoginViewModel", "Response code: ${response.code()}")
if (response.isSuccessful) { if (response.isSuccessful) {
val userAuthResponse = response.body() // Получаем ответ с ролью пользователя val userAuthResponse = response.body() // Получаем JSON-ответ
userAuthResponse?.let { Log.d("LoginViewModel", "User Auth Response: $userAuthResponse") // Логируем ответ
SessionManager.userLogin = username // Сохраняем логин
SessionManager.userRole = it.role // Сохраняем роль // Обработка JSON-ответа
if (userAuthResponse != null) {
SessionManager.userLogin = username
SessionManager.userRole = userAuthResponse.role // Сохраняем роль
_state.value = LoginState(success = true) // Успешная авторизация
} else {
_state.value = LoginState(error = "Ошибка авторизации: Неверные учетные данные.")
} }
_state.value = LoginState(success = true, userAuthResponse = userAuthResponse)
} else { } else {
_state.value = LoginState(error = "Ошибка авторизации") _state.value = LoginState(error = "Ошибка авторизации: ${response.message()}")
} }
} catch (e: Exception) { } catch (e: Exception) {
e.printStackTrace() e.printStackTrace()
@ -60,13 +53,14 @@ class LoginViewModel @Inject constructor(
} }
private fun isValidUsername(username: String): Boolean { private fun isValidUsername(username: String): Boolean {
return username.length >= 3 && !username.first().isDigit() && username.all { it.isLetterOrDigit() } return username.isNotEmpty() // Пример проверки логина
} }
}
data class LoginState( // Состояние аутентификации
val success: Boolean = false, data class LoginState(
val error: String? = null, val success: Boolean = false, // Успешность аутентификации
val maintenance: Boolean = false, val userAuthResponse: UserAuthResponse? = null, // Ответ с информацией о пользователе
val userAuthResponse: UserAuthResponse? = null // Добавляем поле для хранения информации о роли val error: String? = null, // Сообщение об ошибке
) val maintenance: Boolean = false // Состояние техобслуживания
} )