From 478f6334ec238da1aa30f91189b28f804d662c95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Munsch?= Date: Fri, 11 Aug 2023 17:40:30 +0200 Subject: [PATCH] Move PWD sync to Home sync button + Fix VNC arg edit not saving in profile --- .../avnc/ui/ldc/KioskParameterActivity.kt | 19 ++- .../ui/ldc/KioskParameterPasswordActivity.kt | 121 ------------------ .../ui/ldc/fragments/KioskHomeFragment.kt | 92 +++++++++++++ .../gaurav/avnc/ui/ldc/lib/ApplicationInfo.kt | 4 +- 4 files changed, 112 insertions(+), 124 deletions(-) diff --git a/app/src/main/java/com/gaurav/avnc/ui/ldc/KioskParameterActivity.kt b/app/src/main/java/com/gaurav/avnc/ui/ldc/KioskParameterActivity.kt index 27e5a97..fcdcb76 100644 --- a/app/src/main/java/com/gaurav/avnc/ui/ldc/KioskParameterActivity.kt +++ b/app/src/main/java/com/gaurav/avnc/ui/ldc/KioskParameterActivity.kt @@ -8,11 +8,14 @@ import android.view.View import android.widget.Button import android.widget.EditText import android.widget.Toast +import androidx.activity.viewModels import androidx.appcompat.app.AppCompatActivity import androidx.preference.PreferenceManager.getDefaultSharedPreferences import com.gaurav.avnc.R +import com.gaurav.avnc.model.ServerProfile import com.gaurav.avnc.ui.ldc.lib.ApplicationInfo import com.gaurav.avnc.ui.ldc.lib.exceptions.InvalidUriException +import com.gaurav.avnc.viewmodel.HomeViewModel import java.net.InetAddress import java.net.UnknownHostException @@ -111,7 +114,21 @@ class KioskParameterActivity : AppCompatActivity(), View.OnClickListener { } catch(e: UnknownHostException) { toastMessage(this, "L'adresse ip n'est pas valide") } - toastMessage(this, "Enregistré") + Thread { + val viewModel by viewModels() + var profile = appInfo.loadProfile(viewModel) + if (profile == null) { + profile = ServerProfile() + profile.host = appInfo.vncArgIp.hostAddress + profile.port = appInfo.vncArgPort + viewModel.insertProfile(profile) + } else { + profile.host = appInfo.vncArgIp.hostAddress + profile.port = appInfo.vncArgPort + viewModel.updateProfile(profile) + } + toastMessage(this, "Enregistré") + }.start() } /** diff --git a/app/src/main/java/com/gaurav/avnc/ui/ldc/KioskParameterPasswordActivity.kt b/app/src/main/java/com/gaurav/avnc/ui/ldc/KioskParameterPasswordActivity.kt index 73084a2..68d6a88 100644 --- a/app/src/main/java/com/gaurav/avnc/ui/ldc/KioskParameterPasswordActivity.kt +++ b/app/src/main/java/com/gaurav/avnc/ui/ldc/KioskParameterPasswordActivity.kt @@ -1,6 +1,5 @@ package com.gaurav.avnc.ui.ldc -import android.annotation.SuppressLint import android.app.Activity import android.content.Context import android.content.Intent @@ -14,23 +13,9 @@ import android.widget.EditText import android.widget.TextView.OnEditorActionListener import android.widget.Toast import androidx.appcompat.app.AppCompatActivity -import androidx.core.graphics.toColorInt import androidx.preference.PreferenceManager.getDefaultSharedPreferences -import com.fasterxml.jackson.core.JsonProcessingException -import com.fasterxml.jackson.core.type.TypeReference -import com.fasterxml.jackson.databind.ObjectMapper import com.gaurav.avnc.R import com.gaurav.avnc.ui.ldc.lib.ApplicationInfo -import com.github.fge.jsonschema.main.JsonSchema -import com.github.fge.jsonschema.main.JsonSchemaFactory -import okhttp3.Call -import okhttp3.Callback -import okhttp3.OkHttpClient -import okhttp3.Request -import okhttp3.Response -import org.json.* -import java.io.IOException -import java.io.InputStream class KioskParameterPasswordActivity : AppCompatActivity(), View.OnClickListener { @@ -81,7 +66,6 @@ class KioskParameterPasswordActivity : AppCompatActivity(), View.OnClickListener // * AppInfo Refresh appInfo.refreshConfigProperties() appInfo.retrieveDeviceNetworkInfo(applicationContext) - //fetchConfigPassword(this) } // * Action UI events @@ -112,111 +96,6 @@ class KioskParameterPasswordActivity : AppCompatActivity(), View.OnClickListener runOnUiThread {editTextPassword.setTextColor(Color.BLACK) } startActivity(Intent(this, KioskParameterActivity::class.java)) } - - /** - * Try to fetch config password from server - */ - private fun fetchConfigPassword(activity: KioskParameterPasswordActivity) { - val client = OkHttpClient() - val request = Request.Builder() - .url(activity.appInfo.appConfigUri.toString()) - .build() - - manageButtons(false) - val callback = object : Callback { - override fun onFailure(call: Call, e: IOException) { - toastMessage(activity, "Erreur : ${e.message} - ${e.cause?.message}") - manageButtons(true) - return - } - @SuppressLint("SetTextI18n") - override fun onResponse(call: Call, response: Response) { - response.use { - if (!response.isSuccessful) { - toastMessage(activity ,"Erreur (${response.code}) : ${response.message}") - manageButtons(true) - return - } - val bodyResponse = response.body?.string() - - if (bodyResponse == null) { - toastMessage(activity, "Erreur réponse vide du serveur") - manageButtons(true) - return - } - - runOnUiThread { - if(!isJSONValid(bodyResponse)) { - toastMessage(activity, "Erreur réponse invalide du serveur") - manageButtons(true) - } else { - saveJSONPassword(bodyResponse) - manageButtons(true) - } - } - return - } - } - } - client.newCall(request).enqueue(callback) - } - - /** - * Manage button to hold - */ - private fun manageButtons(enable: Boolean) { - runOnUiThread { - if (enable) { - btnSubmitPassword?.isEnabled = true - btnSubmitPassword?.isClickable = true - btnSubmitPassword?.setBackgroundColor("#D4021D".toColorInt()) - } else { - btnSubmitPassword?.isEnabled = false - btnSubmitPassword?.isClickable = false - btnSubmitPassword?.setBackgroundColor(Color.GRAY) - } - } - } - - /** - * Validate Json parameter schema - */ - private fun isJSONValid(jsonString: String): Boolean { - // * Validate JSON - try { - JSONObject(jsonString) - } catch (ex: JSONException) { - try { - JSONArray(jsonString) - } catch (ex1: JSONException) { - return false - } - } - - // * Validate JSON Schema - return try { - val factory: JsonSchemaFactory = JsonSchemaFactory.byDefault() - val inputStream: InputStream = assets.open("security.schema.json"); - val schemaString = inputStream.bufferedReader().use{it.readText()} - - val m = ObjectMapper() - val jsonSchema: JsonSchema = factory.getJsonSchema(m.readTree(schemaString)) - - jsonSchema.validate(m.readTree(jsonString)).isSuccess - } catch(e: JsonProcessingException) { - false - } - } - - /** - * Save Json password - */ - private fun saveJSONPassword(jsonString: String) { - val mapper = ObjectMapper() - val configNode = mapper.readValue>(jsonString, object : TypeReference>() {}) - appInfo.setPassword(configNode["password"]!!) - } - /** * Display toast message */ diff --git a/app/src/main/java/com/gaurav/avnc/ui/ldc/fragments/KioskHomeFragment.kt b/app/src/main/java/com/gaurav/avnc/ui/ldc/fragments/KioskHomeFragment.kt index e63cb58..29b5510 100644 --- a/app/src/main/java/com/gaurav/avnc/ui/ldc/fragments/KioskHomeFragment.kt +++ b/app/src/main/java/com/gaurav/avnc/ui/ldc/fragments/KioskHomeFragment.kt @@ -16,6 +16,9 @@ import androidx.core.graphics.toColorInt import androidx.core.view.isVisible import androidx.fragment.app.Fragment import androidx.fragment.app.viewModels +import com.fasterxml.jackson.core.JsonProcessingException +import com.fasterxml.jackson.core.type.TypeReference +import com.fasterxml.jackson.databind.ObjectMapper import com.gaurav.avnc.R import com.gaurav.avnc.model.ServerProfile import com.gaurav.avnc.ui.ldc.KioskActivity @@ -24,6 +27,8 @@ import com.gaurav.avnc.ui.ldc.events.AppSwitchedToForegroundEvent import com.gaurav.avnc.ui.ldc.events.NetworkStateChangedEvent import com.gaurav.avnc.ui.vnc.startVncActivity import com.gaurav.avnc.viewmodel.HomeViewModel +import com.github.fge.jsonschema.main.JsonSchema +import com.github.fge.jsonschema.main.JsonSchemaFactory import com.google.common.net.InetAddresses import okhttp3.Call import okhttp3.Callback @@ -36,8 +41,12 @@ import org.apache.commons.csv.CSVRecord import org.greenrobot.eventbus.EventBus import org.greenrobot.eventbus.Subscribe import org.greenrobot.eventbus.ThreadMode +import org.json.JSONArray +import org.json.JSONException +import org.json.JSONObject import java.io.BufferedReader import java.io.IOException +import java.io.InputStream import java.io.Reader import java.net.InetAddress import java.util.regex.Matcher @@ -175,6 +184,8 @@ class KioskHomeFragment : Fragment(), View.OnClickListener { manageButtons(true) // Download Config File loadDistantConfiguration(fragment) + // Download Password config + fetchConfigPassword(fragment) } /** @@ -279,6 +290,87 @@ class KioskHomeFragment : Fragment(), View.OnClickListener { client.newCall(request).enqueue(callback) } + /** + * Try to fetch config password from server + */ + private fun fetchConfigPassword(fragment: KioskHomeFragment) { + val activity = (fragment.activity as KioskActivity) + val client = OkHttpClient() + val request = Request.Builder() + .url(activity.appInfo.appConfigUri.toString()) + .build() + + val callback = object : Callback { + override fun onFailure(call: Call, e: IOException) { + toastMessage(activity, "Erreur : ${e.message} - ${e.cause?.message}") + return + } + @SuppressLint("SetTextI18n") + override fun onResponse(call: Call, response: Response) { + response.use { + if (!response.isSuccessful) { + toastMessage(activity ,"Erreur (${response.code}) : ${response.message}") + return + } + val bodyResponse = response.body?.string() + + if (bodyResponse == null) { + toastMessage(activity, "Erreur réponse vide du serveur") + return + } + + if(!isJSONValid(activity, bodyResponse)) { + toastMessage(activity, "Erreur réponse invalide du serveur") + } else { + saveJSONPassword(activity, bodyResponse) + } + return + } + } + } + client.newCall(request).enqueue(callback) + } + + /** + * Validate Json parameter schema + */ + private fun isJSONValid(activity: KioskActivity, jsonString: String): Boolean { + // * Validate JSON + try { + JSONObject(jsonString) + } catch (ex: JSONException) { + try { + JSONArray(jsonString) + } catch (ex1: JSONException) { + return false + } + } + + // * Validate JSON Schema + return try { + val factory: JsonSchemaFactory = JsonSchemaFactory.byDefault() + val inputStream: InputStream = activity.assets.open("security.schema.json"); + val schemaString = inputStream.bufferedReader().use{it.readText()} + + val m = ObjectMapper() + val jsonSchema: JsonSchema = factory.getJsonSchema(m.readTree(schemaString)) + + jsonSchema.validate(m.readTree(jsonString)).isSuccess + } catch(e: JsonProcessingException) { + false + } + } + + /** + * Save Json password + */ + private fun saveJSONPassword(activity: KioskActivity, jsonString: String) { + val mapper = ObjectMapper() + val configNode = mapper.readValue>(jsonString, object : TypeReference>() {}) + activity.appInfo.setPassword(configNode["password"]!!) + } + + /** * Display network info */ diff --git a/app/src/main/java/com/gaurav/avnc/ui/ldc/lib/ApplicationInfo.kt b/app/src/main/java/com/gaurav/avnc/ui/ldc/lib/ApplicationInfo.kt index 9c2fed3..d2f9757 100644 --- a/app/src/main/java/com/gaurav/avnc/ui/ldc/lib/ApplicationInfo.kt +++ b/app/src/main/java/com/gaurav/avnc/ui/ldc/lib/ApplicationInfo.kt @@ -43,7 +43,7 @@ class ApplicationInfo(private var preferences: SharedPreferences) { /** * Shared preferences items for dynamic update */ - val sharedPreferencesFields = mapOf>( + private val sharedPreferencesFields = mapOf>( "Int" to setOf("vncArgPort"), "InetAddress" to setOf("vncArgIp"), "String" to setOf("configPassword", "configServerFqdn", "configServerPath", "appConfigPath"), @@ -87,7 +87,7 @@ class ApplicationInfo(private var preferences: SharedPreferences) { refreshConfigProperties() SharedPreferences.OnSharedPreferenceChangeListener { sharedPreferences, s -> sharedPreferencesFields.forEach(fun (key, items) { - if (items.indexOf(s) !== -1) { + if (items.indexOf(s) != -1) { when (key) { "Int" -> initProp(s, sharedPreferences.getString(s, readInstanceProperty(this, s).toString()