basic auth - mne horosho...

This commit is contained in:
shipovnikaaa 2025-02-20 10:52:44 +03:00
parent eae3035683
commit 5129a8b3f2
9 changed files with 167 additions and 38 deletions

View File

@ -0,0 +1,82 @@
kotlin version: 2.0.21
error message: Daemon compilation failed: null
java.lang.Exception
at org.jetbrains.kotlin.daemon.common.CompileService$CallResult$Error.get(CompileService.kt:69)
at org.jetbrains.kotlin.daemon.common.CompileService$CallResult$Error.get(CompileService.kt:65)
at org.jetbrains.kotlin.compilerRunner.GradleKotlinCompilerWork.compileWithDaemon(GradleKotlinCompilerWork.kt:240)
at org.jetbrains.kotlin.compilerRunner.GradleKotlinCompilerWork.compileWithDaemonOrFallbackImpl(GradleKotlinCompilerWork.kt:159)
at org.jetbrains.kotlin.compilerRunner.GradleKotlinCompilerWork.run(GradleKotlinCompilerWork.kt:111)
at org.jetbrains.kotlin.compilerRunner.GradleCompilerRunnerWithWorkers$GradleKotlinCompilerWorkAction.execute(GradleCompilerRunnerWithWorkers.kt:76)
at org.gradle.workers.internal.DefaultWorkerServer.execute(DefaultWorkerServer.java:63)
at org.gradle.workers.internal.NoIsolationWorkerFactory$1$1.create(NoIsolationWorkerFactory.java:66)
at org.gradle.workers.internal.NoIsolationWorkerFactory$1$1.create(NoIsolationWorkerFactory.java:62)
at org.gradle.internal.classloader.ClassLoaderUtils.executeInClassloader(ClassLoaderUtils.java:100)
at org.gradle.workers.internal.NoIsolationWorkerFactory$1.lambda$execute$0(NoIsolationWorkerFactory.java:62)
at org.gradle.workers.internal.AbstractWorker$1.call(AbstractWorker.java:44)
at org.gradle.workers.internal.AbstractWorker$1.call(AbstractWorker.java:41)
at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:209)
at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:204)
at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:66)
at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:59)
at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:166)
at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:59)
at org.gradle.internal.operations.DefaultBuildOperationRunner.call(DefaultBuildOperationRunner.java:53)
at org.gradle.workers.internal.AbstractWorker.executeWrappedInBuildOperation(AbstractWorker.java:41)
at org.gradle.workers.internal.NoIsolationWorkerFactory$1.execute(NoIsolationWorkerFactory.java:59)
at org.gradle.workers.internal.DefaultWorkerExecutor.lambda$submitWork$0(DefaultWorkerExecutor.java:174)
at java.base/java.util.concurrent.FutureTask.run(Unknown Source)
at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner.runExecution(DefaultConditionalExecutionQueue.java:195)
at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner.access$700(DefaultConditionalExecutionQueue.java:128)
at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner$1.run(DefaultConditionalExecutionQueue.java:170)
at org.gradle.internal.Factories$1.create(Factories.java:31)
at org.gradle.internal.work.DefaultWorkerLeaseService.withLocks(DefaultWorkerLeaseService.java:267)
at org.gradle.internal.work.DefaultWorkerLeaseService.runAsWorkerThread(DefaultWorkerLeaseService.java:131)
at org.gradle.internal.work.DefaultWorkerLeaseService.runAsWorkerThread(DefaultWorkerLeaseService.java:136)
at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner.runBatch(DefaultConditionalExecutionQueue.java:165)
at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner.run(DefaultConditionalExecutionQueue.java:134)
at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source)
at java.base/java.util.concurrent.FutureTask.run(Unknown Source)
at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:64)
at org.gradle.internal.concurrent.AbstractManagedExecutor$1.run(AbstractManagedExecutor.java:48)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.base/java.lang.Thread.run(Unknown Source)
Caused by: java.nio.file.DirectoryNotEmptyException: C:\Users\User\AppData\Local\Temp\kotlin-backups3293833258477019099
at java.base/sun.nio.fs.WindowsFileSystemProvider.implDelete(Unknown Source)
at java.base/sun.nio.fs.AbstractFileSystemProvider.delete(Unknown Source)
at java.base/java.nio.file.Files.delete(Unknown Source)
at org.jetbrains.kotlin.incremental.RecoverableCompilationTransaction$cleanupStash$2$1$1.invoke(CompilationTransaction.kt:244)
at org.jetbrains.kotlin.incremental.RecoverableCompilationTransaction$cleanupStash$2$1$1.invoke(CompilationTransaction.kt:244)
at org.jetbrains.kotlin.incremental.RecoverableCompilationTransaction.cleanupStash$lambda$11$lambda$10$lambda$9(CompilationTransaction.kt:244)
at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(Unknown Source)
at java.base/java.util.ArrayList.forEach(Unknown Source)
at java.base/java.util.stream.SortedOps$RefSortingSink.end(Unknown Source)
at java.base/java.util.stream.Sink$ChainedReference.end(Unknown Source)
at java.base/java.util.stream.AbstractPipeline.copyInto(Unknown Source)
at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(Unknown Source)
at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(Unknown Source)
at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(Unknown Source)
at java.base/java.util.stream.AbstractPipeline.evaluate(Unknown Source)
at java.base/java.util.stream.ReferencePipeline.forEach(Unknown Source)
at org.jetbrains.kotlin.incremental.RecoverableCompilationTransaction.cleanupStash(CompilationTransaction.kt:244)
at org.jetbrains.kotlin.incremental.RecoverableCompilationTransaction.close(CompilationTransaction.kt:254)
at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.tryCompileIncrementally(IncrementalCompilerRunner.kt:747)
at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compile(IncrementalCompilerRunner.kt:120)
at org.jetbrains.kotlin.daemon.CompileServiceImplBase.execIncrementalCompiler(CompileServiceImpl.kt:675)
at org.jetbrains.kotlin.daemon.CompileServiceImplBase.access$execIncrementalCompiler(CompileServiceImpl.kt:92)
at org.jetbrains.kotlin.daemon.CompileServiceImpl.compile(CompileServiceImpl.kt:1660)
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(Unknown Source)
at java.base/java.lang.reflect.Method.invoke(Unknown Source)
at java.rmi/sun.rmi.server.UnicastServerRef.dispatch(Unknown Source)
at java.rmi/sun.rmi.transport.Transport$1.run(Unknown Source)
at java.rmi/sun.rmi.transport.Transport$1.run(Unknown Source)
at java.base/java.security.AccessController.doPrivileged(Unknown Source)
at java.rmi/sun.rmi.transport.Transport.serviceCall(Unknown Source)
at java.rmi/sun.rmi.transport.tcp.TCPTransport.handleMessages(Unknown Source)
at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(Unknown Source)
at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(Unknown Source)
at java.base/java.security.AccessController.doPrivileged(Unknown Source)
at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(Unknown Source)
... 3 more

View File

@ -2,4 +2,4 @@ package ru.myitschool.work.ui.admin
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
@Serializable @Serializable
data class AdminDestination(val username: String) data class AdminDestination(val username: String, val password: String)

View File

@ -35,6 +35,9 @@ class AdminFragment : Fragment(R.layout.fragment_admin) {
val username = val username =
findNavController().currentBackStackEntry?.toRoute<AdminDestination>()?.username findNavController().currentBackStackEntry?.toRoute<AdminDestination>()?.username
username?.let { user -> username?.let { user ->
val password =
findNavController().currentBackStackEntry?.toRoute<AdminDestination>()?.password
password?.let { password ->
binding.loginadmin.addTextChangedListener(TextChangedListener { binding.loginadmin.addTextChangedListener(TextChangedListener {
viewModel.onUsernameChanged(it) viewModel.onUsernameChanged(it)
@ -42,19 +45,20 @@ class AdminFragment : Fragment(R.layout.fragment_admin) {
subscribe() subscribe()
binding.adminName.text = user binding.adminName.text = user
binding.find.setOnClickListener { binding.find.setOnClickListener {
login(binding.loginadmin.text.toString()) login(user, password, binding.loginadmin.text.toString())
} }
binding.backAdmin.setOnClickListener { binding.backAdmin.setOnClickListener {
findNavController().apply { findNavController().apply {
popBackStack<AdminDestination>(true) popBackStack<AdminDestination>(true)
navigate(MainDestination(user)) navigate(MainDestination(user, password = password))
}
} }
} }
} }
} }
private fun login(username: String) { private fun login(username: String, password: String, loginPerson : String) {
viewModel.loadPersonInfo(username) { viewModel.loadPersonInfo(username, password, loginPerson) {
viewModel.state.collectWhenStarted(this) { state -> viewModel.state.collectWhenStarted(this) { state ->
if (state.photo.isNotEmpty()) { if (state.photo.isNotEmpty()) {
picasso.load(state.photo).into(binding.photoAdmin) picasso.load(state.photo).into(binding.photoAdmin)

View File

@ -5,6 +5,8 @@ import android.util.Log
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import com.google.gson.GsonBuilder import com.google.gson.GsonBuilder
import createAuthHeader
import createRetrofit
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.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
@ -14,8 +16,10 @@ import kotlinx.coroutines.launch
import retrofit2.HttpException import retrofit2.HttpException
import ru.myitschool.work.data.remote.LoginApi import ru.myitschool.work.data.remote.LoginApi
import ru.myitschool.work.data.remote.ErrorDto import ru.myitschool.work.data.remote.ErrorDto
import ru.myitschool.work.data.remote.PersonInfoDto
import ru.myitschool.work.di.AppModule import ru.myitschool.work.di.AppModule
import ru.myitschool.work.ui.admin.AdminState import ru.myitschool.work.ui.admin.AdminState
import ru.myitschool.work.ui.main.MainState
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import javax.inject.Inject import javax.inject.Inject
@ -34,19 +38,28 @@ class AdminViewModel @Inject constructor(
private val dfo = SimpleDateFormat("yyyy-MM-dd HH:mm") private val dfo = SimpleDateFormat("yyyy-MM-dd HH:mm")
private val dfi= SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss") private val dfi= SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss")
fun loadPersonInfo(username: String, onSuccess: () -> Unit) { private val retrofit = createRetrofit("your_username", "your_password")
private val loginApi = retrofit.create(LoginApi::class.java)
fun loadPersonInfo(username: String, password : String, loginPerson: String, onSuccess: () -> Unit) {
viewModelScope.launch { viewModelScope.launch {
try { try {
val info = api.info(username) val authHeader = createAuthHeader(username = username, password)
val info = loginApi.info(authHeader, loginPerson)
val personInfo = info.body()?.let { responseBody ->
GsonBuilder().create().fromJson(responseBody.string(), PersonInfoDto::class.java)
}
if (personInfo != null) {
_state.update { _state.update {
AdminMainState( AdminMainState(
fullName = info.name, fullName = personInfo.name,
photo = info.photo, photo = personInfo.photo,
position = info.position, position = personInfo.position,
lastVisit = dfo.format(dfi.parse(info.lastVisit)!!), lastVisit = dfo.format(dfi.parse(personInfo.lastVisit)!!),
error = null error = null
) )
} }
}
onSuccess() onSuccess()
} catch (httpException: HttpException) { } catch (httpException: HttpException) {
try { try {

View File

@ -0,0 +1,23 @@
import android.os.Build
import androidx.annotation.RequiresApi
import okhttp3.OkHttpClient
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import ru.myitschool.work.core.Constants
import java.util.Base64
fun createRetrofit(username: String, password: String): Retrofit {
val client = OkHttpClient.Builder()
.build()
return Retrofit.Builder()
.baseUrl(Constants.SERVER_ADDRESS)
.client(client)
.addConverterFactory(GsonConverterFactory.create())
.build()
}
fun createAuthHeader(username: String, password: String): String {
val credentials = "$username:$password"
return "Basic " + Base64.getEncoder().encodeToString(credentials.toByteArray())
}

View File

@ -35,7 +35,7 @@ class LoginFragment : Fragment(R.layout.fragment_login) {
viewModel.tryLogin(username, password) { viewModel.tryLogin(username, password) {
findNavController().apply { findNavController().apply {
popBackStack<LoginDestination>(true) popBackStack<LoginDestination>(true)
navigate(MainDestination(username)) navigate(MainDestination(username, password))
} }
} }
} }

View File

@ -73,6 +73,7 @@ class LoginViewModel @Inject constructor(
onSuccess() onSuccess()
} catch (httpExc: HttpException) { } catch (httpExc: HttpException) {
Log.e("LoginViewModel", "Login failed for $username", httpExc) Log.e("LoginViewModel", "Login failed for $username", httpExc)
_state.update { it.copy(error = "Login failed for: $username") }
try { try {
httpExc.response()?.errorBody()?.string()?.let { errorString -> httpExc.response()?.errorBody()?.string()?.let { errorString ->
val gson = GsonBuilder().create() val gson = GsonBuilder().create()

View File

@ -32,7 +32,7 @@ class MainFragment: Fragment(R.layout.fragment_main) {
val password = findNavController().currentBackStackEntry?.toRoute<MainDestination>()?.password val password = findNavController().currentBackStackEntry?.toRoute<MainDestination>()?.password
password?.let { password -> password?.let { password ->
viewModel.loadPersonInfo(user, password) viewModel.loadPersonInfo(user, password)
binding.refresh.setOnClickListener { viewModel.loadPersonInfo(user) } binding.refresh.setOnClickListener { viewModel.loadPersonInfo(user, password) }
binding.logout.setOnClickListener { binding.logout.setOnClickListener {
viewModel.logout { viewModel.logout {
findNavController().apply { findNavController().apply {
@ -46,7 +46,7 @@ class MainFragment: Fragment(R.layout.fragment_main) {
findNavController().navigate(QrScanDestination) findNavController().navigate(QrScanDestination)
} }
binding.admin.setOnClickListener { binding.admin.setOnClickListener {
findNavController().navigate(AdminDestination(user)) findNavController().navigate(AdminDestination(user, password))
} }
} }
} }

View File

@ -17,6 +17,7 @@ import kotlinx.coroutines.launch
import retrofit2.HttpException import retrofit2.HttpException
import ru.myitschool.work.data.remote.LoginApi import ru.myitschool.work.data.remote.LoginApi
import ru.myitschool.work.data.remote.ErrorDto import ru.myitschool.work.data.remote.ErrorDto
import ru.myitschool.work.data.remote.PersonInfoDto
import ru.myitschool.work.di.AppModule import ru.myitschool.work.di.AppModule
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import javax.inject.Inject import javax.inject.Inject
@ -39,17 +40,22 @@ class MainViewModel @Inject constructor(
fun loadPersonInfo(username: String, password : String) { fun loadPersonInfo(username: String, password : String) {
viewModelScope.launch { viewModelScope.launch {
try { try {
val authHeader = createAuthHeader(username = username, password) val authHeader = createAuthHeader(username = username, password= password)
val info = loginApi.auth(authHeader, username) val info = loginApi.info(authHeader, username)
val personInfo = info.body()?.let { responseBody ->
GsonBuilder().create().fromJson(responseBody.string(), PersonInfoDto::class.java)
}
if (personInfo != null) {
_state.update { _state.update {
MainState( MainState(
fullName = info.name, fullName = personInfo.name,
photo = info.photo, photo = personInfo.photo,
position = info.position, position = personInfo.position,
lastVisit = dfo.format(dfi.parse(info.lastVisit)!!), lastVisit = dfo.format(dfi.parse(personInfo.lastVisit)!!),
error = null error = null
) )
} }
}
} catch (httpException: HttpException) { } catch (httpException: HttpException) {
try { try {
httpException.response()?.errorBody()?.string()?.let { errorString -> httpException.response()?.errorBody()?.string()?.let { errorString ->