summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIván Ávalos <avalos@disroot.org>2023-11-14 14:13:51 -0600
committerTorsten Grote <t@grobox.de>2023-11-28 13:59:37 -0300
commitba51b5e541d888cafdbf479a7e03a116af7050c5 (patch)
treea8b893bd8dd0212cba11cd0af75e95eb8b7a7bd0
parent94ee3a2f114e0345ea7408aacc30e3da9545474c (diff)
downloadtaler-android-ba51b5e541d888cafdbf479a7e03a116af7050c5.tar.gz
taler-android-ba51b5e541d888cafdbf479a7e03a116af7050c5.tar.bz2
taler-android-ba51b5e541d888cafdbf479a7e03a116af7050c5.zip
[wallet] Proper DB import/export functionality
-rw-r--r--wallet/src/main/java/net/taler/wallet/MainViewModel.kt2
-rw-r--r--wallet/src/main/java/net/taler/wallet/backend/WalletBackendApi.kt23
-rw-r--r--wallet/src/main/java/net/taler/wallet/settings/SettingsFragment.kt17
-rw-r--r--wallet/src/main/java/net/taler/wallet/settings/SettingsManager.kt91
-rw-r--r--wallet/src/main/res/drawable/ic_archive.xml21
-rw-r--r--wallet/src/main/res/values/strings.xml6
-rw-r--r--wallet/src/main/res/xml/settings_main.xml8
7 files changed, 150 insertions, 18 deletions
diff --git a/wallet/src/main/java/net/taler/wallet/MainViewModel.kt b/wallet/src/main/java/net/taler/wallet/MainViewModel.kt
index 15fe7e4..4614474 100644
--- a/wallet/src/main/java/net/taler/wallet/MainViewModel.kt
+++ b/wallet/src/main/java/net/taler/wallet/MainViewModel.kt
@@ -83,7 +83,7 @@ class MainViewModel(
val refundManager = RefundManager(api, viewModelScope)
val exchangeManager: ExchangeManager = ExchangeManager(api, viewModelScope)
val peerManager: PeerManager = PeerManager(api, exchangeManager, viewModelScope)
- val settingsManager: SettingsManager = SettingsManager(app.applicationContext, viewModelScope)
+ val settingsManager: SettingsManager = SettingsManager(app.applicationContext, api, viewModelScope)
val accountManager: AccountManager = AccountManager(api, viewModelScope)
val depositManager: DepositManager = DepositManager(api, viewModelScope)
diff --git a/wallet/src/main/java/net/taler/wallet/backend/WalletBackendApi.kt b/wallet/src/main/java/net/taler/wallet/backend/WalletBackendApi.kt
index bf6f371..ea58dd7 100644
--- a/wallet/src/main/java/net/taler/wallet/backend/WalletBackendApi.kt
+++ b/wallet/src/main/java/net/taler/wallet/backend/WalletBackendApi.kt
@@ -23,6 +23,7 @@ import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import kotlinx.serialization.KSerializer
+import kotlinx.serialization.json.JsonObject
import kotlinx.serialization.json.decodeFromJsonElement
import net.taler.wallet.backend.TalerErrorCode.NONE
import org.json.JSONObject
@@ -86,4 +87,26 @@ class WalletBackendApi(
WalletResponse.Error(info)
}
}
+
+ // Returns raw JSON response instead of serialized object
+ suspend inline fun rawRequest(
+ operation: String,
+ noinline args: (JSONObject.() -> JSONObject)? = null,
+ ): WalletResponse<JsonObject> = withContext(Dispatchers.Default) {
+ val json = BackendManager.json
+ try {
+ when (val response = sendRequest(operation, args?.invoke(JSONObject()))) {
+ is ApiResponse.Response -> {
+ WalletResponse.Success(response.result)
+ }
+ is ApiResponse.Error -> {
+ val error: TalerErrorInfo = json.decodeFromJsonElement(response.error)
+ WalletResponse.Error(error)
+ }
+ }
+ } catch (e: Exception) {
+ val info = TalerErrorInfo(NONE, "", e.toString())
+ WalletResponse.Error(info)
+ }
+ }
}
diff --git a/wallet/src/main/java/net/taler/wallet/settings/SettingsFragment.kt b/wallet/src/main/java/net/taler/wallet/settings/SettingsFragment.kt
index f5826c9..54d6dc0 100644
--- a/wallet/src/main/java/net/taler/wallet/settings/SettingsFragment.kt
+++ b/wallet/src/main/java/net/taler/wallet/settings/SettingsFragment.kt
@@ -18,6 +18,7 @@ package net.taler.wallet.settings
import android.os.Bundle
import android.view.View
+import androidx.activity.result.contract.ActivityResultContracts.OpenDocument
import androidx.activity.result.contract.ActivityResultContracts.CreateDocument
import androidx.fragment.app.activityViewModels
import androidx.preference.Preference
@@ -47,6 +48,7 @@ class SettingsFragment : PreferenceFragmentCompat() {
private lateinit var prefWithdrawTest: Preference
private lateinit var prefLogcat: Preference
private lateinit var prefExportDb: Preference
+ private lateinit var prefImportDb: Preference
private lateinit var prefVersionApp: Preference
private lateinit var prefVersionCore: Preference
private lateinit var prefVersionExchange: Preference
@@ -58,6 +60,7 @@ class SettingsFragment : PreferenceFragmentCompat() {
prefWithdrawTest,
prefLogcat,
prefExportDb,
+ prefImportDb,
prefVersionApp,
prefVersionCore,
prefVersionExchange,
@@ -71,9 +74,13 @@ class SettingsFragment : PreferenceFragmentCompat() {
settingsManager.exportLogcat(uri)
}
private val dbExportLauncher =
- registerForActivityResult(CreateDocument("application/x-sqlite3")) { uri ->
+ registerForActivityResult(CreateDocument("application/json")) { uri ->
settingsManager.exportDb(uri)
}
+ private val dbImportLauncher =
+ registerForActivityResult(OpenDocument()) { uri ->
+ settingsManager.importDb(uri)
+ }
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
setPreferencesFromResource(R.xml.settings_main, rootKey)
@@ -81,6 +88,7 @@ class SettingsFragment : PreferenceFragmentCompat() {
prefWithdrawTest = findPreference("pref_testkudos")!!
prefLogcat = findPreference("pref_logcat")!!
prefExportDb = findPreference("pref_export_db")!!
+ prefImportDb = findPreference("pref_import_db")!!
prefVersionApp = findPreference("pref_version_app")!!
prefVersionCore = findPreference("pref_version_core")!!
prefVersionExchange = findPreference("pref_version_protocol_exchange")!!
@@ -127,10 +135,13 @@ class SettingsFragment : PreferenceFragmentCompat() {
true
}
prefExportDb.setOnPreferenceClickListener {
- dbExportLauncher.launch("taler-wallet-db-${currentTimeMillis()}.sql")
+ dbExportLauncher.launch("taler-wallet-db-${currentTimeMillis()}.json")
+ true
+ }
+ prefImportDb.setOnPreferenceClickListener {
+ dbImportLauncher.launch(arrayOf("application/json"))
true
}
-
prefTest.setOnPreferenceClickListener {
model.runIntegrationTest()
true
diff --git a/wallet/src/main/java/net/taler/wallet/settings/SettingsManager.kt b/wallet/src/main/java/net/taler/wallet/settings/SettingsManager.kt
index 349c7b1..0b4cbe9 100644
--- a/wallet/src/main/java/net/taler/wallet/settings/SettingsManager.kt
+++ b/wallet/src/main/java/net/taler/wallet/settings/SettingsManager.kt
@@ -25,14 +25,19 @@ import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
+import kotlinx.serialization.encodeToString
+import kotlinx.serialization.json.Json
import net.taler.wallet.R
-import net.taler.wallet.backend.WALLET_DB
+import net.taler.wallet.backend.WalletBackendApi
+import net.taler.wallet.backend.WalletResponse.Error
+import net.taler.wallet.backend.WalletResponse.Success
+import org.json.JSONObject
class SettingsManager(
private val context: Context,
+ private val api: WalletBackendApi,
private val scope: CoroutineScope,
) {
-
fun exportLogcat(uri: Uri?) {
if (uri == null) {
onLogExportError()
@@ -65,20 +70,76 @@ class SettingsManager(
onDbExportError()
return
}
+
scope.launch(Dispatchers.IO) {
- try {
- context.contentResolver.openOutputStream(uri, "wt")?.use { outputStream ->
- context.openFileInput(WALLET_DB).use { inputStream ->
- inputStream.copyTo(outputStream)
+ when (val response = api.rawRequest("exportDb")) {
+ is Success -> {
+ try {
+ context.contentResolver.openOutputStream(uri, "wt")?.use { outputStream ->
+ val data = Json.encodeToString(response.result)
+ val writer = outputStream.bufferedWriter()
+ writer.write(data)
+ writer.close()
+ }
+ } catch(e: Exception) {
+ Log.e(SettingsManager::class.simpleName, "Error exporting db: ", e)
+ withContext(Dispatchers.Main) {
+ onDbExportError()
+ }
+ return@launch
}
- } ?: onDbExportError()
- } catch (e: Exception) {
- Log.e(SettingsManager::class.simpleName, "Error exporting db: ", e)
- onDbExportError()
- return@launch
+
+ withContext(Dispatchers.Main) {
+ Toast.makeText(context, R.string.settings_db_export_success, LENGTH_LONG).show()
+ }
+ }
+ is Error -> {
+ Log.e(SettingsManager::class.simpleName, "Error exporting db: ${response.error}")
+ withContext(Dispatchers.Main) {
+ onDbExportError()
+ }
+ return@launch
+ }
}
- withContext(Dispatchers.Main) {
- Toast.makeText(context, R.string.settings_db_export_success, LENGTH_LONG).show()
+ }
+ }
+
+ fun importDb(uri: Uri?) {
+ if (uri == null) {
+ onDbImportError()
+ return
+ }
+
+ scope.launch(Dispatchers.IO) {
+ context.contentResolver.openInputStream(uri)?.use { inputStream ->
+ try {
+ val reader = inputStream.bufferedReader()
+ val strData = reader.readText()
+ reader.close()
+ val jsonData = JSONObject(strData)
+ when (val response = api.rawRequest("importDb") {
+ put("dump", jsonData)
+ }) {
+ is Success -> {
+ withContext(Dispatchers.Main) {
+ Toast.makeText(context, R.string.settings_db_import_success, LENGTH_LONG).show()
+ }
+ }
+ is Error -> {
+ Log.e(SettingsManager::class.simpleName, "Error importing db: ${response.error}")
+ withContext(Dispatchers.Main) {
+ onDbImportError()
+ }
+ return@launch
+ }
+ }
+ } catch (e: Exception) {
+ Log.e(SettingsManager::class.simpleName, "Error importing db: ", e)
+ withContext(Dispatchers.Main) {
+ onDbImportError()
+ }
+ return@launch
+ }
}
}
}
@@ -87,4 +148,8 @@ class SettingsManager(
Toast.makeText(context, R.string.settings_db_export_error, LENGTH_LONG).show()
}
+ private fun onDbImportError() {
+ Toast.makeText(context, R.string.settings_db_import_error, LENGTH_LONG).show()
+ }
+
}
diff --git a/wallet/src/main/res/drawable/ic_archive.xml b/wallet/src/main/res/drawable/ic_archive.xml
new file mode 100644
index 0000000..58a032c
--- /dev/null
+++ b/wallet/src/main/res/drawable/ic_archive.xml
@@ -0,0 +1,21 @@
+<!--
+ ~ This file is part of GNU Taler
+ ~ (C) 2023 Taler Systems S.A.
+ ~
+ ~ GNU Taler is free software; you can redistribute it and/or modify it under the
+ ~ terms of the GNU General Public License as published by the Free Software
+ ~ Foundation; either version 3, or (at your option) any later version.
+ ~
+ ~ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ ~ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ ~ A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ ~
+ ~ You should have received a copy of the GNU General Public License along with
+ ~ GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+ -->
+
+<vector android:height="24dp" android:tint="?attr/colorControlNormal"
+ android:viewportHeight="24" android:viewportWidth="24"
+ android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+ <path android:fillColor="@android:color/white" android:pathData="M20.54,5.23l-1.39,-1.68C18.88,3.21 18.47,3 18,3H6c-0.47,0 -0.88,0.21 -1.16,0.55L3.46,5.23C3.17,5.57 3,6.02 3,6.5V19c0,1.1 0.9,2 2,2h14c1.1,0 2,-0.9 2,-2V6.5c0,-0.48 -0.17,-0.93 -0.46,-1.27zM12,17.5L6.5,12H10v-2h4v2h3.5L12,17.5zM5.12,5l0.81,-1h12l0.94,1H5.12z"/>
+</vector>
diff --git a/wallet/src/main/res/values/strings.xml b/wallet/src/main/res/values/strings.xml
index 3b05ae9..2533820 100644
--- a/wallet/src/main/res/values/strings.xml
+++ b/wallet/src/main/res/values/strings.xml
@@ -257,10 +257,14 @@ GNU Taler is immune against many types of fraud, such as phishing of credit card
<string name="settings_logcat_summary">Save internal log</string>
<string name="settings_logcat_error">Error exporting log</string>
<string name="settings_logcat_success">Log exported to file</string>
- <string name="settings_db_export">Database</string>
+ <string name="settings_db_export">Export database</string>
<string name="settings_db_export_summary">Save internal database</string>
+ <string name="settings_db_import">Import database</string>
+ <string name="settings_db_import_summary">Restore database from file</string>
<string name="settings_db_export_error">Error exporting database</string>
+ <string name="settings_db_import_error">Error importing database</string>
<string name="settings_db_export_success">Database exported to file</string>
+ <string name="settings_db_import_success">Database imported from file</string>
<string name="settings_version_app">App Version</string>
<string name="settings_version_core">Wallet Core Version</string>
<string name="settings_version_protocol_exchange">Supported Exchange Versions</string>
diff --git a/wallet/src/main/res/xml/settings_main.xml b/wallet/src/main/res/xml/settings_main.xml
index 3a6d991..739e119 100644
--- a/wallet/src/main/res/xml/settings_main.xml
+++ b/wallet/src/main/res/xml/settings_main.xml
@@ -56,6 +56,14 @@
tools:isPreferenceVisible="true" />
<Preference
+ app:icon="@drawable/ic_archive"
+ app:isPreferenceVisible="false"
+ app:key="pref_import_db"
+ app:summary="@string/settings_db_import_summary"
+ app:title="@string/settings_db_import"
+ tools:isPreferenceVisible="true" />
+
+ <Preference
app:icon="@drawable/ic_account_balance_wallet"
app:isPreferenceVisible="false"
app:key="pref_version_app"