From 12cf0eecafc8b6364ad2e63676489341f91af8f5 Mon Sep 17 00:00:00 2001 From: Isidro Henoch Date: Mon, 6 Dec 2021 02:33:20 -0600 Subject: WIP: Adds the token persistance --- .../mx/trackermap/TrackerMap/android/TrackerApp.kt | 2 +- .../TrackerMap/android/session/LoginActivity.kt | 2 - .../TrackerMap/android/session/LoginFragment.kt | 1 + .../TrackerMap/android/session/LoginViewModel.kt | 12 ++++ shared/build.gradle.kts | 4 ++ .../TrackerMap/client/apis/SessionApi.kt | 75 ++++++++++++++-------- .../TrackerMap/client/infrastructure/ApiClient.kt | 13 ++++ 7 files changed, 80 insertions(+), 29 deletions(-) diff --git a/androidApp/src/main/java/mx/trackermap/TrackerMap/android/TrackerApp.kt b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/TrackerApp.kt index a8efbf2..9331dcc 100644 --- a/androidApp/src/main/java/mx/trackermap/TrackerMap/android/TrackerApp.kt +++ b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/TrackerApp.kt @@ -15,7 +15,7 @@ class TrackerApp: Application() { super.onCreate() val appModule = module { - single { "https://etbsa.net/api/" } + single { "https://etbsa.net/api" } single { SessionApi(get()) } viewModel { LoginViewModel(get(), get()) } diff --git a/androidApp/src/main/java/mx/trackermap/TrackerMap/android/session/LoginActivity.kt b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/session/LoginActivity.kt index 3aec7b8..3fbab80 100644 --- a/androidApp/src/main/java/mx/trackermap/TrackerMap/android/session/LoginActivity.kt +++ b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/session/LoginActivity.kt @@ -1,8 +1,6 @@ package mx.trackermap.TrackerMap.android.session import android.os.Bundle -import android.os.PersistableBundle -import android.util.Log import androidx.appcompat.app.AppCompatActivity import mx.trackermap.TrackerMap.android.R diff --git a/androidApp/src/main/java/mx/trackermap/TrackerMap/android/session/LoginFragment.kt b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/session/LoginFragment.kt index 5039a7c..82d11d1 100644 --- a/androidApp/src/main/java/mx/trackermap/TrackerMap/android/session/LoginFragment.kt +++ b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/session/LoginFragment.kt @@ -32,6 +32,7 @@ class LoginFragment : Fragment() { setupEvents() setupObservers() + loginViewModel.restoreSession() } override fun onDestroyView() { diff --git a/androidApp/src/main/java/mx/trackermap/TrackerMap/android/session/LoginViewModel.kt b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/session/LoginViewModel.kt index 9df78aa..82c5bf9 100644 --- a/androidApp/src/main/java/mx/trackermap/TrackerMap/android/session/LoginViewModel.kt +++ b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/session/LoginViewModel.kt @@ -29,6 +29,18 @@ class LoginViewModel( private val loginResultEmitter = EventEmitter() val loginResult: EventSource = loginResultEmitter + fun restoreSession() { + viewModelScope.launch { + try { + val user = sessionApi.sessionGet() + Log.d("LoginViewModel", user.toString()) + loginResultEmitter.emit(LoginResult.Success) + } catch (e: Exception) { + Log.d("LoginViewModel", "No session") + } + } + } + fun login() { val email = email.value!!.toString().trim() val password = password.value!!.toString().trim() diff --git a/shared/build.gradle.kts b/shared/build.gradle.kts index 4c6e870..6853a0c 100644 --- a/shared/build.gradle.kts +++ b/shared/build.gradle.kts @@ -6,6 +6,7 @@ plugins { kotlin { val ktor_version = "1.6.6" + val settings_version = "0.8.1" android() @@ -28,6 +29,9 @@ kotlin { implementation("io.ktor:ktor-client-serialization:$ktor_version") implementation("ch.qos.logback:logback-classic:1.2.6") + implementation("com.russhwolf:multiplatform-settings:$settings_version") + implementation("com.russhwolf:multiplatform-settings-no-arg:$settings_version") + implementation("org.jetbrains.kotlinx:kotlinx-datetime:0.3.1") } } diff --git a/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/client/apis/SessionApi.kt b/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/client/apis/SessionApi.kt index f80135d..4344de0 100644 --- a/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/client/apis/SessionApi.kt +++ b/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/client/apis/SessionApi.kt @@ -11,40 +11,45 @@ */ package mx.trackermap.TrackerMap.client.apis -import io.ktor.client.request.forms.FormDataContent -import io.ktor.http.Parameters +import com.russhwolf.settings.Settings import mx.trackermap.TrackerMap.client.models.User - import mx.trackermap.TrackerMap.client.infrastructure.* +val ACCESS_TOKEN_KEY = "access_token" + class SessionApi(basePath: kotlin.String = "https://demo.traccar.org/api") : ApiClient(basePath) { /** * Close the Session - * + * * @return void */ suspend fun sessionDelete(): Unit { - + val localVariableConfig = RequestConfig( - RequestMethod.DELETE, - "/session" + RequestMethod.DELETE, + "/session" ) val response = request( - localVariableConfig + localVariableConfig ) return when (response.responseType) { ResponseType.Success -> Unit ResponseType.Informational -> TODO() ResponseType.Redirection -> TODO() - ResponseType.ClientError -> throw ClientException((response as ClientError<*>).body as? String ?: "Client error") - ResponseType.ServerError -> throw ServerException((response as ServerError<*>).message ?: "Server error") + ResponseType.ClientError -> throw ClientException( + (response as ClientError<*>).body as? String ?: "Client error" + ) + ResponseType.ServerError -> throw ServerException( + (response as ServerError<*>).message ?: "Server error" + ) } } + /** * Fetch Session information - * + * * @param token (optional) * @return User */ @@ -52,47 +57,65 @@ class SessionApi(basePath: kotlin.String = "https://demo.traccar.org/api") : Api suspend fun sessionGet(token: kotlin.String? = null): User { val localVariableQuery: MultiValueMap = mapOf("token" to listOf("$token")) val localVariableConfig = RequestConfig( - RequestMethod.GET, - "/session", query = localVariableQuery + RequestMethod.GET, + "/session", query = localVariableQuery ) val response = request( - localVariableConfig + localVariableConfig ) return when (response.responseType) { ResponseType.Success -> (response as Success<*>).data as User ResponseType.Informational -> TODO() ResponseType.Redirection -> TODO() - ResponseType.ClientError -> throw ClientException((response as ClientError<*>).body as? String ?: "Client error") - ResponseType.ServerError -> throw ServerException((response as ServerError<*>).message ?: "Server error") + ResponseType.ClientError -> throw ClientException( + (response as ClientError<*>).body as? String ?: "Client error" + ) + ResponseType.ServerError -> throw ServerException( + (response as ServerError<*>).message ?: "Server error" + ) } } + /** * Create a new Session - * - * @param email - * @param password + * + * @param email + * @param password * @return User */ @Suppress("UNCHECKED_CAST") suspend fun sessionPost(email: String, password: String): User { val localVariableBody = mapOf("email" to email, "password" to password) - + val localVariableHeaders = mapOf("Content-Type" to "application/x-www-form-urlencoded") val localVariableConfig = RequestConfig( - RequestMethod.POST, - "/session", headers = localVariableHeaders + RequestMethod.POST, + "/session", headers = localVariableHeaders ) val response = request( - localVariableConfig, localVariableBody + localVariableConfig, localVariableBody ) return when (response.responseType) { - ResponseType.Success -> (response as Success<*>).data as User + ResponseType.Success -> { + val cookie = response.headers + .values + .flatten() + .find { it.contains("JSESSIONID") }!! + .replace("; Path=/", "") + val settings = Settings() + settings.putString(ACCESS_TOKEN_KEY, cookie) + (response as Success<*>).data as User + } ResponseType.Informational -> TODO() ResponseType.Redirection -> TODO() - ResponseType.ClientError -> throw ClientException((response as ClientError<*>).body as? String ?: "Client error") - ResponseType.ServerError -> throw ServerException((response as ServerError<*>).message ?: "Server error") + ResponseType.ClientError -> throw ClientException( + (response as ClientError<*>).body as? String ?: "Client error" + ) + ResponseType.ServerError -> throw ServerException( + (response as ServerError<*>).message ?: "Server error" + ) } } } diff --git a/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/client/infrastructure/ApiClient.kt b/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/client/infrastructure/ApiClient.kt index 91d0aa2..4ec7b46 100644 --- a/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/client/infrastructure/ApiClient.kt +++ b/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/client/infrastructure/ApiClient.kt @@ -1,5 +1,7 @@ package mx.trackermap.TrackerMap.client.infrastructure +import com.russhwolf.settings.Settings +import com.russhwolf.settings.string import io.ktor.client.* import io.ktor.client.call.* import io.ktor.client.engine.cio.* @@ -14,6 +16,7 @@ import io.ktor.client.request.forms.FormDataContent import io.ktor.client.statement.* import io.ktor.http.* import io.ktor.util.* +import mx.trackermap.TrackerMap.client.apis.ACCESS_TOKEN_KEY import kotlinx.serialization.json.Json as KotlinJson open class ApiClient(val baseUrl: String) { @@ -52,6 +55,13 @@ open class ApiClient(val baseUrl: String) { ) } + var token: String = "" + + init { + val settings = Settings() + token = settings.getString(ACCESS_TOKEN_KEY, "") + } + protected inline fun fillRequest( requestBuilder: HttpRequestBuilder, content: T, @@ -155,6 +165,9 @@ open class ApiClient(val baseUrl: String) { } } + if (token.isNotEmpty()) { + request.headers["Cookie"] = token + } val response: HttpResponse = client.request(request) // TODO: handle specific mapping types. e.g. Map> -- cgit v1.2.3