Skip to content

Commit

Permalink
Merge branch 'feature/1572-ResetTanMechanism'
Browse files Browse the repository at this point in the history
  • Loading branch information
mtotschnig committed Oct 6, 2024
2 parents 7afe8bf + 77e4010 commit 0cd575f
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 40 deletions.
39 changes: 28 additions & 11 deletions fints/src/main/java/org/totschnig/fints/Banking.kt
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ class Banking : ProtectedFragmentActivity() {
viewModel.messageShown()
}
})
}
}
}
}
setContent {
Expand Down Expand Up @@ -204,7 +204,7 @@ class Banking : ProtectedFragmentActivity() {
) {
if (data.value.isEmpty()) {
Text(
text = stringResource(org.totschnig.fints.R.string.no_bank_added_yet),
text = stringResource(RF.string.no_bank_added_yet),
modifier = Modifier.align(Alignment.Center)
)
} else {
Expand All @@ -231,9 +231,13 @@ class Banking : ProtectedFragmentActivity() {
bankingCredentials.value =
BankingCredentials.fromBank(it)
},
onMigrate = {
migrationDialogShown.value = it
}
onMigrate = if (it.version == 1) {
{ migrationDialogShown.value = it }
} else null,
onResetTanMechanism =
if (viewModel.hasStoredTanMech(it.id)) {
{ viewModel.resetTanMechanism(it.id) }
} else null
)
}
}
Expand Down Expand Up @@ -272,7 +276,7 @@ class Banking : ProtectedFragmentActivity() {
workState: BankingViewModel.WorkState,
bankingCredentials: MutableState<BankingCredentials>,
errorState: State<String?>,
dismiss: (success: Boolean) -> Unit
dismiss: (success: Boolean) -> Unit,
) {
when (dialogState) {
DialogState.AccountSelection -> {
Expand Down Expand Up @@ -374,7 +378,7 @@ class Banking : ProtectedFragmentActivity() {
onClick = null
)
Text(
text = getString(org.totschnig.fints.R.string.import_maximum),
text = getString(RF.string.import_maximum),
style = MaterialTheme.typography.bodyMedium
)
}
Expand Down Expand Up @@ -585,15 +589,20 @@ fun BankRow(
bank: Bank,
onDelete: (Bank) -> Unit = {},
onShow: (Bank) -> Unit = {},
onMigrate: (Bank) -> Unit = {}
onResetTanMechanism: ((Bank) -> Unit)? = null,
onMigrate: ((Bank) -> Unit)? = null,
) {
val showMenu = remember { mutableStateOf(false) }
Row(
modifier = Modifier.clickable { showMenu.value = true },
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(6.dp)
) {
BankIconImpl(modifier = Modifier.padding(2.dp).size(48.dp), bank = bank)
BankIconImpl(
modifier = Modifier
.padding(2.dp)
.size(48.dp), bank = bank
)
Column {
Text(bank.bankName)
Text(bank.blz + " / " + bank.bic)
Expand All @@ -610,14 +619,22 @@ fun BankRow(
icon = Icons.Filled.Checklist
) { onShow(bank) }
)
if (bank.version == 1) {
onMigrate?.let {
add(
MenuEntry(
command = "MIGRATION",
label = UiText.StringValue("v1 -> v2")
) { onMigrate(bank) }
)
}
onResetTanMechanism?.let {
add(
MenuEntry(
command = "MIGRATION",
label = RF.string.reset_stored_configuration
) { onResetTanMechanism(bank) }
)
}
}
)
HierarchicalMenu(showMenu, menu)
Expand All @@ -629,7 +646,7 @@ fun AccountRow(
selectable: Boolean,
selected: String?,
targetOptions: List<Pair<Long, String>>,
onSelectionChange: (Boolean, Long) -> Unit
onSelectionChange: (Boolean, Long) -> Unit,
) {
Row {
if (selectable) {
Expand Down
69 changes: 40 additions & 29 deletions fints/src/main/java/org/totschnig/fints/BankingViewModel.kt
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import android.os.Bundle
import androidx.annotation.WorkerThread
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.SavedStateHandle
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.CompletableDeferred
import kotlinx.coroutines.flow.MutableStateFlow
Expand Down Expand Up @@ -106,7 +105,7 @@ data class SecMech(val id: String, val name: String) {
}
}

class BankingViewModel(application: Application, private val savedStateHandle: SavedStateHandle) :
class BankingViewModel(application: Application) :
ContentResolvingAndroidViewModel(application) {
@Inject
lateinit var tracker: Tracker
Expand All @@ -118,25 +117,39 @@ class BankingViewModel(application: Application, private val savedStateHandle: S
)
}

var selectedTanMedium: String?
get() = savedStateHandle["selectedTanMedium"]
set(value) {
savedStateHandle["selectedTanMedium"] = value
}

var selectedSecMech: String?
get() = savedStateHandle["selectedSecMech"]
set(value) {
savedStateHandle["selectedSecMech"] = value
}

private val hbciProperties = Properties().also {
it["client.product.name"] = "02F84CA8EC793B72255C747B4"
if (BuildConfig.DEBUG) {
it["log.loglevel.default"] = HBCIUtils.LOG_INTERN.toString()
}
}

private fun keySelectedTanMedium(bankId: Long) = "selectedTanMedium_$bankId"
private fun keySelectedSecMech(bankId: Long) = "selectedSecMech_$bankId"

fun selectedTanMedium(bankId: Long) =
prefHandler.getString(keySelectedTanMedium(bankId))

fun selectedSecMech(bankId: Long) =
prefHandler.getString(keySelectedSecMech(bankId))

fun hasStoredTanMech(bankId: Long): Boolean =
selectedSecMech(bankId) != null || selectedTanMedium(bankId) != null

fun resetTanMechanism(bankId: Long) {
prefHandler.remove(keySelectedSecMech(bankId))
prefHandler.remove(keySelectedTanMedium(bankId))
}

private fun persistSelectedTanMedium(bankId: Long, tanMedium: String) {
prefHandler.putString(keySelectedTanMedium(bankId), tanMedium)
}

private fun persistSelectedSecMech(bankId: Long, secMech: String) {
prefHandler.putString(keySelectedSecMech(bankId), secMech)
}


private val _tanRequested = MutableLiveData<TanRequest?>(null)
val tanRequested: LiveData<TanRequest?> = _tanRequested

Expand Down Expand Up @@ -651,22 +664,16 @@ class BankingViewModel(application: Application, private val savedStateHandle: S

inner class MyHBCICallback(private val bankingCredentials: BankingCredentials) :
AbstractHBCICallback() {
private val keySelectedTanMedium: String?
get() = bankingCredentials.bank?.let { "selectedTanMedium_${it.id}" }
private val keySelectedSecMech: String?
get() = bankingCredentials.bank?.let { "selectedSecMech_${it.id}" }

init {
keySelectedTanMedium?.let { selectedTanMedium = prefHandler.getString(it) }
keySelectedSecMech?.let { selectedSecMech = prefHandler.getString(it) }
}
private var selectedTanMedium: String? = null

private fun persistSelectedTanMedium() {
keySelectedTanMedium?.let { prefHandler.putString(it, selectedTanMedium) }
}
private var selectedSecMech: String? = null

private fun persistSelectedSecMech() {
keySelectedSecMech?.let { prefHandler.putString(it, selectedSecMech) }
init {
bankingCredentials.bank?.let {
selectedTanMedium = selectedTanMedium(it.id)
selectedSecMech = selectedSecMech(it.id)
}
}

override fun log(msg: String, level: Int, date: Date, trace: StackTraceElement) {
Expand Down Expand Up @@ -740,7 +747,9 @@ class BankingViewModel(application: Application, private val savedStateHandle: S
?: runBlocking {
requestSecMech(options).await()?.let { (secMec, shouldPersist) ->
selectedSecMech = secMec
if (shouldPersist) persistSelectedSecMech()
if (shouldPersist && bankingCredentials.bank != null) {
persistSelectedSecMech(bankingCredentials.bank.id, secMec)
}
secMec
} ?: throw HBCI_Exception("Security mechanism selection cancelled")
}
Expand Down Expand Up @@ -768,7 +777,9 @@ class BankingViewModel(application: Application, private val savedStateHandle: S
} else selectedTanMedium.takeIf { options.contains(it) } ?: runBlocking {
requestTanMedium(options).await()?.let { (medium, shouldPersist) ->
selectedTanMedium = medium
if (shouldPersist) persistSelectedTanMedium()
if (shouldPersist && bankingCredentials.bank != null) {
persistSelectedTanMedium(bankingCredentials.bank.id, medium)
}
medium
} ?: throw HBCI_Exception("TAN media selection cancelled")
}
Expand Down
1 change: 1 addition & 0 deletions fints/src/main/res/values-de/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -50,4 +50,5 @@
<string name="migration_description_1548">Vor Version 3.8.8 wurde die PIN, die Sie für die Kommunikation mit dem FinTS-Server angegeben haben, auch als Passwort für die Verschlüsselung lokal gespeicherter sensibler Informationen (Passport) verwendet, was eine Änderung der PIN unmöglich machte. Seit Version 3.8.8 wird stattdessen ein zufällig generiertes Passwort verwendet, das in eine Datei geschrieben wird, die mit einem im Android KeyStore gespeicherten Schlüssel verschlüsselt ist. Wenn Sie die PIN angeben, die Sie beim Einrichten dieser FinTS-Verbindung verwendet haben, wird diese auf die gleiche sichere Weise gespeichert und kann somit zum Entschlüsseln des Passports verwendet werden, unabhängig von der PIN, die dadurch aktualisiert werden kann.</string>
<string name="password_securely_stored">Password sicher gespeichert.</string>
<string name="migrate">Migrieren</string>
<string name="reset_stored_configuration">TAN-Verfahren zurücksetzen</string>
</resources>
1 change: 1 addition & 0 deletions fints/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -52,4 +52,5 @@
<string name="migration_description_1548">Prior to version 3.8.8, the PIN you provided for communicating with the FinTS server, was also used as password for encrypting locally stored sensitive information (passport), which made it impossible to change the PIN. Since version 3.8.8, a randomly generated password, that is written to a file encrypted with a key stored in the Android KeyStore, is used instead. By providing the PIN that you used when you setup this FinTS connection, it will be saved in the same secure way, and thus can be used for decrypting the passport, independent of the PIN that can now be updated.</string>
<string name="password_securely_stored">Password securely stored.</string>
<string name="migrate">Migrate</string>
<string name="reset_stored_configuration">Reset stored TAN mechanism</string>
</resources>

0 comments on commit 0cd575f

Please sign in to comment.