From 907c1c5d1ce4f2e26b05f076385ca724100f9671 Mon Sep 17 00:00:00 2001 From: Terebov_Maksim Date: Wed, 19 Feb 2025 16:56:30 +0300 Subject: [PATCH] day2_commit_13_back_to_Json --- .../java/ru/myitschool/work/api/ApiModule.kt | 15 ++++- .../java/ru/myitschool/work/api/ApiService.kt | 15 ++--- .../ru/myitschool/work/api/AuthInterceptor.kt | 16 +++++ .../java/ru/myitschool/work/core/Constants.kt | 2 +- .../myitschool/work/ui/login/LoginFragment.kt | 19 +++--- .../work/ui/login/LoginViewModel.kt | 62 +++++++++---------- 6 files changed, 72 insertions(+), 57 deletions(-) create mode 100644 app/src/main/java/ru/myitschool/work/api/AuthInterceptor.kt diff --git a/app/src/main/java/ru/myitschool/work/api/ApiModule.kt b/app/src/main/java/ru/myitschool/work/api/ApiModule.kt index a13ebd5..1b02705 100644 --- a/app/src/main/java/ru/myitschool/work/api/ApiModule.kt +++ b/app/src/main/java/ru/myitschool/work/api/ApiModule.kt @@ -4,9 +4,9 @@ import dagger.Module import dagger.Provides import dagger.hilt.InstallIn import dagger.hilt.components.SingletonComponent +import okhttp3.OkHttpClient import retrofit2.Retrofit import retrofit2.converter.gson.GsonConverterFactory -import ru.myitschool.work.api.ApiService import ru.myitschool.work.core.Constants import javax.inject.Singleton @@ -16,9 +16,20 @@ object ApiModule { @Provides @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() .baseUrl(Constants.SERVER_ADDRESS) + .client(client) .addConverterFactory(GsonConverterFactory.create()) .build() } diff --git a/app/src/main/java/ru/myitschool/work/api/ApiService.kt b/app/src/main/java/ru/myitschool/work/api/ApiService.kt index 9328037..cd239ad 100644 --- a/app/src/main/java/ru/myitschool/work/api/ApiService.kt +++ b/app/src/main/java/ru/myitschool/work/api/ApiService.kt @@ -6,14 +6,17 @@ import retrofit2.http.GET import retrofit2.http.PATCH import retrofit2.http.POST import retrofit2.http.Path +import retrofit2.http.Query interface ApiService { // Метод для аутентификации - @POST("/api/auth") // Изменено на POST и путь к аутентификации + @GET("/api/auth") // Используем GET для аутентификации suspend fun authenticate( - @Body payload: AuthRequest // Передаем объект с логином и паролем - ): Response // Возвращаем UserAuthResponse + @Query("login") login: String, // Передаем логин как параметр запроса + @Query("password") password: String // Передаем пароль как параметр запроса + ): Response // Возвращаем JSON как объект UserAuthResponse + // Другие методы... @GET("/api/{login}/info") // Получение информации о пользователе suspend fun getUserInfo(@Path("login") login: String): Response> @@ -30,12 +33,6 @@ interface ApiService { suspend fun getAllWorkers(): Response> } -// Модель данных для запроса аутентификации -data class AuthRequest( - val login: String, - val password: String // Поле для пароля -) - // Модель данных для ответа аутентификации data class UserAuthResponse( val role: String // Добавляем поле для роли diff --git a/app/src/main/java/ru/myitschool/work/api/AuthInterceptor.kt b/app/src/main/java/ru/myitschool/work/api/AuthInterceptor.kt new file mode 100644 index 0000000..2e635b1 --- /dev/null +++ b/app/src/main/java/ru/myitschool/work/api/AuthInterceptor.kt @@ -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) + } +} \ No newline at end of file diff --git a/app/src/main/java/ru/myitschool/work/core/Constants.kt b/app/src/main/java/ru/myitschool/work/core/Constants.kt index 7a5d665..235327b 100644 --- a/app/src/main/java/ru/myitschool/work/core/Constants.kt +++ b/app/src/main/java/ru/myitschool/work/core/Constants.kt @@ -1,5 +1,5 @@ package ru.myitschool.work.core // БЕРИТЕ И ИЗМЕНЯЙТЕ ХОСТ ТОЛЬКО ЗДЕСЬ И НЕ БЕРИТЕ ИЗ ДРУГИХ МЕСТ. ФАЙЛ ПЕРЕМЕЩАТЬ НЕЛЬЗЯ object Constants { - const val SERVER_ADDRESS = "const val SERVER_ADDRESS = \"http://localhost:8080\"\n" + const val SERVER_ADDRESS = "http://192.168.1.131:8080" } \ No newline at end of file diff --git a/app/src/main/java/ru/myitschool/work/ui/login/LoginFragment.kt b/app/src/main/java/ru/myitschool/work/ui/login/LoginFragment.kt index 4d85985..5d79f87 100644 --- a/app/src/main/java/ru/myitschool/work/ui/login/LoginFragment.kt +++ b/app/src/main/java/ru/myitschool/work/ui/login/LoginFragment.kt @@ -85,15 +85,12 @@ class LoginFragment : Fragment(R.layout.fragment_login) { } private fun subscribe() { - viewModel.state.collectWhenStarted(this) { state -> - binding.loading.visibleOrGone(false) + lifecycleScope.launch { + viewModel.state.collect { state -> + binding.loading.visibleOrGone(false) - try { if (state.maintenance) { showMaintenanceDialog() // Показываем диалог о техработах - } else if (state.error != null) { - binding.error.text = state.error - binding.error.visibility = View.VISIBLE } else if (state.success) { binding.error.visibility = View.GONE authPreferences.saveLoginState(true) @@ -106,11 +103,11 @@ class LoginFragment : Fragment(R.layout.fragment_login) { } 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()) .setTitle("Технические работы") .setMessage("Проводятся техработы, пожалуйста, подождите.") - .setPositiveButton("ОК") { dialog, _ -> dialog.dismiss() } + .setPositiveButton("ОК ") { dialog, _ -> dialog.dismiss() } .setCancelable(false) .show() } diff --git a/app/src/main/java/ru/myitschool/work/ui/login/LoginViewModel.kt b/app/src/main/java/ru/myitschool/work/ui/login/LoginViewModel.kt index a62b768..25dcb8a 100644 --- a/app/src/main/java/ru/myitschool/work/ui/login/LoginViewModel.kt +++ b/app/src/main/java/ru/myitschool/work/ui/login/LoginViewModel.kt @@ -1,53 +1,46 @@ package ru.myitschool.work.ui.login -import android.content.Context +import android.util.Log import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel -import dagger.hilt.android.qualifiers.ApplicationContext import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.launch -import okhttp3.Credentials -import retrofit2.Retrofit -import retrofit2.converter.gson.GsonConverterFactory import ru.myitschool.work.SessionManager import ru.myitschool.work.api.ApiService -import ru.myitschool.work.api.AuthRequest import ru.myitschool.work.api.UserAuthResponse -import ru.myitschool.work.core.Constants import javax.inject.Inject @HiltViewModel class LoginViewModel @Inject constructor( - @ApplicationContext private val context: Context, + private val apiService: ApiService ) : ViewModel() { - private val _state = MutableStateFlow(LoginState()) - val state = _state.asStateFlow() - private val apiService: ApiService by lazy { - Retrofit.Builder() - .baseUrl(Constants.SERVER_ADDRESS) - .addConverterFactory(GsonConverterFactory.create()) - .build() - .create(ApiService::class.java) - } + private val _state = MutableStateFlow(LoginState()) + val state: StateFlow get() = _state fun authenticate(username: String, password: String) { if (isValidUsername(username)) { viewModelScope.launch { try { - val payload = AuthRequest(username, password) // Создаем объект запроса - val response = apiService.authenticate(payload) // Вызываем метод аутентификации + val response = apiService.authenticate(username, password) + Log.d("LoginViewModel", "Response code: ${response.code()}") + if (response.isSuccessful) { - val userAuthResponse = response.body() // Получаем ответ с ролью пользователя - userAuthResponse?.let { - SessionManager.userLogin = username // Сохраняем логин - SessionManager.userRole = it.role // Сохраняем роль + val userAuthResponse = response.body() // Получаем JSON-ответ + Log.d("LoginViewModel", "User Auth Response: $userAuthResponse") // Логируем ответ + + // Обработка 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 { - _state.value = LoginState(error = "Ошибка авторизации") + _state.value = LoginState(error = "Ошибка авторизации: ${response.message()}") } } catch (e: Exception) { e.printStackTrace() @@ -60,13 +53,14 @@ class LoginViewModel @Inject constructor( } 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, - val error: String? = null, - val maintenance: Boolean = false, - val userAuthResponse: UserAuthResponse? = null // Добавляем поле для хранения информации о роли - ) -} \ No newline at end of file +// Состояние аутентификации +data class LoginState( + val success: Boolean = false, // Успешность аутентификации + val userAuthResponse: UserAuthResponse? = null, // Ответ с информацией о пользователе + val error: String? = null, // Сообщение об ошибке + val maintenance: Boolean = false // Состояние техобслуживания +) \ No newline at end of file