simplify :core:interfaces

This commit is contained in:
Milos Kozak 2023-09-18 14:23:00 +02:00
parent 91d19b51dc
commit 46c2abdc5b
25 changed files with 154 additions and 121 deletions

View file

@ -0,0 +1,7 @@
package info.nightscout.interfaces.maintenance
import android.os.Parcelable
import kotlinx.parcelize.Parcelize
@Parcelize
data class PrefMetadata(var value: String, var status: PrefsStatus, var info: String? = null) : Parcelable

View file

@ -0,0 +1,11 @@
package info.nightscout.interfaces.maintenance
import android.content.Context
interface PrefsMetadataKey {
val key: String
val icon: Int
val label: Int
fun formatForDisplay(context: Context, value: String): String
}

View file

@ -0,0 +1,8 @@
package info.nightscout.interfaces.maintenance
import android.os.Parcelable
interface PrefsStatus : Parcelable {
val icon: Int
}

View file

@ -1,17 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Maintenance -->
<string name="metadata_label_format">File format</string>
<string name="metadata_label_created_at">Created at</string>
<string name="metadata_label_aaps_version">AAPS Version</string>
<string name="metadata_label_aaps_flavour">Build Variant</string>
<string name="metadata_label_device_name">Exporting device patient name</string>
<string name="metadata_label_device_model">Exporting device model</string>
<string name="metadata_label_encryption">File encryption</string>
<string name="metadata_format_new">New encrypted format</string>
<string name="metadata_format_debug">New debug format (unencrypted)</string>
<string name="metadata_format_other">Unknown export format</string>
<!-- PumpPluginBase -->
<string name="pump_driver_changed" comment="26 characters max for translation">Pump driver changed.</string>

View file

@ -1,6 +1,5 @@
package info.nightscout.implementation.utils
import info.nightscout.interfaces.R
import info.nightscout.interfaces.utils.DecimalFormatter
import info.nightscout.shared.interfaces.ResourceHelper
import java.text.DecimalFormat

View file

@ -3,6 +3,7 @@ plugins {
id 'kotlin-android'
id 'kotlin-kapt'
id 'kotlin-allopen'
id 'kotlin-parcelize'
}
apply from: "${project.rootDir}/core/main/android_dependencies.gradle"

View file

@ -44,7 +44,7 @@ import info.nightscout.interfaces.maintenance.Prefs
import info.nightscout.interfaces.maintenance.PrefsFile
import info.nightscout.interfaces.maintenance.PrefsFormat
import info.nightscout.interfaces.maintenance.PrefsMetadataKey
import info.nightscout.interfaces.maintenance.PrefsStatus
import info.nightscout.interfaces.maintenance.PrefsStatusImpl
import info.nightscout.interfaces.protection.PasswordCheck
import info.nightscout.interfaces.storage.Storage
import info.nightscout.interfaces.ui.UiInteraction
@ -114,12 +114,12 @@ class ImportExportPrefsImpl @Inject constructor(
val metadata: MutableMap<PrefsMetadataKey, PrefMetadata> = mutableMapOf()
metadata[PrefsMetadataKey.DEVICE_NAME] = PrefMetadata(detectUserName(context), PrefsStatus.OK)
metadata[PrefsMetadataKey.CREATED_AT] = PrefMetadata(dateUtil.toISOString(dateUtil.now()), PrefsStatus.OK)
metadata[PrefsMetadataKey.AAPS_VERSION] = PrefMetadata(config.VERSION_NAME, PrefsStatus.OK)
metadata[PrefsMetadataKey.AAPS_FLAVOUR] = PrefMetadata(config.FLAVOR, PrefsStatus.OK)
metadata[PrefsMetadataKey.DEVICE_MODEL] = PrefMetadata(config.currentDeviceModelString, PrefsStatus.OK)
metadata[PrefsMetadataKey.ENCRYPTION] = PrefMetadata("Enabled", PrefsStatus.OK)
metadata[PrefsMetadataKeyImpl.DEVICE_NAME] = PrefMetadata(detectUserName(context), PrefsStatusImpl.OK)
metadata[PrefsMetadataKeyImpl.CREATED_AT] = PrefMetadata(dateUtil.toISOString(dateUtil.now()), PrefsStatusImpl.OK)
metadata[PrefsMetadataKeyImpl.AAPS_VERSION] = PrefMetadata(config.VERSION_NAME, PrefsStatusImpl.OK)
metadata[PrefsMetadataKeyImpl.AAPS_FLAVOUR] = PrefMetadata(config.FLAVOR, PrefsStatusImpl.OK)
metadata[PrefsMetadataKeyImpl.DEVICE_MODEL] = PrefMetadata(config.currentDeviceModelString, PrefsStatusImpl.OK)
metadata[PrefsMetadataKeyImpl.ENCRYPTION] = PrefMetadata("Enabled", PrefsStatusImpl.OK)
return metadata
}
@ -133,7 +133,7 @@ class ImportExportPrefsImpl @Inject constructor(
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S || ActivityCompat.checkSelfPermission(context, Manifest.permission.BLUETOOTH_CONNECT) == PackageManager.PERMISSION_GRANTED) {
(context.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager?)?.adapter?.name
} else null
} catch (e: Exception){
} catch (e: Exception) {
null
}
val n4 = Settings.System.getString(context.contentResolver, "device_name")
@ -219,7 +219,7 @@ class ImportExportPrefsImpl @Inject constructor(
) {
// current master password was not the one used for decryption, so we prompt for old password...
if (!importOk && (prefs.metadata[PrefsMetadataKey.ENCRYPTION]?.status == PrefsStatus.ERROR)) {
if (!importOk && (prefs.metadata[PrefsMetadataKeyImpl.ENCRYPTION]?.status == PrefsStatusImpl.ERROR)) {
askForEncryptionPass(
activity, R.string.preferences_import_canceled, R.string.old_master_password,
R.string.different_password_used, R.string.master_password_will_be_replaced
@ -303,6 +303,7 @@ class ImportExportPrefsImpl @Inject constructor(
override fun importCustomWatchface(fragment: Fragment) {
fragment.activity?.let { importCustomWatchface(it) }
}
override fun importCustomWatchface(activity: FragmentActivity) {
try {
if (activity is DaggerAppCompatActivityWithResult)
@ -317,7 +318,7 @@ class ImportExportPrefsImpl @Inject constructor(
override fun exportCustomWatchface(customWatchface: CwfData, withDate: Boolean) {
prefFileList.ensureExportDirExists()
val newFile = prefFileList.newCwfFile(customWatchface.metadata[CwfMetadataKey.CWF_FILENAME] ?:"", withDate)
val newFile = prefFileList.newCwfFile(customWatchface.metadata[CwfMetadataKey.CWF_FILENAME] ?: "", withDate)
ZipWatchfaceFormat.saveCustomWatchface(newFile, customWatchface)
}
@ -374,7 +375,7 @@ class ImportExportPrefsImpl @Inject constructor(
var importOk = true
for ((_, value) in prefs.metadata) {
if (value.status == PrefsStatus.ERROR)
if (value.status == PrefsStatusImpl.ERROR)
importOk = false
}
return importOk

View file

@ -14,7 +14,7 @@ import info.nightscout.interfaces.maintenance.PrefMetadataMap
import info.nightscout.interfaces.maintenance.PrefsFile
import info.nightscout.interfaces.maintenance.PrefsImportDir
import info.nightscout.interfaces.maintenance.PrefsMetadataKey
import info.nightscout.interfaces.maintenance.PrefsStatus
import info.nightscout.interfaces.maintenance.PrefsStatusImpl
import info.nightscout.interfaces.storage.Storage
import info.nightscout.interfaces.versionChecker.VersionCheckerUtils
import info.nightscout.rx.bus.RxBus
@ -89,8 +89,8 @@ class PrefFileListProviderImpl @Inject constructor(
// we sort only if we have metadata to be used for that
if (loadMetadata) {
prefFiles.sortWith(
compareByDescending<PrefsFile> { it.metadata[PrefsMetadataKey.AAPS_FLAVOUR]?.status }
.thenByDescending { it.metadata[PrefsMetadataKey.CREATED_AT]?.value }
compareByDescending<PrefsFile> { it.metadata[PrefsMetadataKeyImpl.AAPS_FLAVOUR]?.status as PrefsStatusImpl }
.thenByDescending { it.metadata[PrefsMetadataKeyImpl.CREATED_AT]?.value }
)
}
@ -169,29 +169,29 @@ class PrefFileListProviderImpl @Inject constructor(
override fun newCwfFile(filename: String, withDate: Boolean): File {
val timeLocal = LocalDateTime.now().toString(DateTimeFormat.forPattern("yyyy-MM-dd'_'HHmmss"))
return if (withDate) File(exportsPath, "${filename}_$timeLocal${ZipWatchfaceFormat.CWF_EXTENTION}") else File(exportsPath,"${filename}${ZipWatchfaceFormat.CWF_EXTENTION}")
return if (withDate) File(exportsPath, "${filename}_$timeLocal${ZipWatchfaceFormat.CWF_EXTENTION}") else File(exportsPath, "${filename}${ZipWatchfaceFormat.CWF_EXTENTION}")
}
// check metadata for known issues, change their status and add info with explanations
override fun checkMetadata(metadata: Map<PrefsMetadataKey, PrefMetadata>): Map<PrefsMetadataKey, PrefMetadata> {
val meta = metadata.toMutableMap()
meta[PrefsMetadataKey.AAPS_FLAVOUR]?.let { flavour ->
meta[PrefsMetadataKeyImpl.AAPS_FLAVOUR]?.let { flavour ->
val flavourOfPrefs = flavour.value
if (flavour.value != config.get().FLAVOR) {
flavour.status = PrefsStatus.WARN
flavour.status = PrefsStatusImpl.WARN
flavour.info = rh.gs(R.string.metadata_warning_different_flavour, flavourOfPrefs, config.get().FLAVOR)
}
}
meta[PrefsMetadataKey.DEVICE_MODEL]?.let { model ->
meta[PrefsMetadataKeyImpl.DEVICE_MODEL]?.let { model ->
if (model.value != config.get().currentDeviceModelString) {
model.status = PrefsStatus.WARN
model.status = PrefsStatusImpl.WARN
model.info = rh.gs(R.string.metadata_warning_different_device)
}
}
meta[PrefsMetadataKey.CREATED_AT]?.let { createdAt ->
meta[PrefsMetadataKeyImpl.CREATED_AT]?.let { createdAt ->
try {
val date1 = DateTime.parse(createdAt.value)
val date2 = DateTime.now()
@ -199,26 +199,26 @@ class PrefFileListProviderImpl @Inject constructor(
val daysOld = Days.daysBetween(date1.toLocalDate(), date2.toLocalDate()).days
if (daysOld > IMPORT_AGE_NOT_YET_OLD_DAYS) {
createdAt.status = PrefsStatus.WARN
createdAt.status = PrefsStatusImpl.WARN
createdAt.info = rh.gs(R.string.metadata_warning_old_export, daysOld.toString())
}
} catch (e: Exception) {
createdAt.status = PrefsStatus.WARN
createdAt.status = PrefsStatusImpl.WARN
createdAt.info = rh.gs(R.string.metadata_warning_date_format)
}
}
meta[PrefsMetadataKey.AAPS_VERSION]?.let { version ->
meta[PrefsMetadataKeyImpl.AAPS_VERSION]?.let { version ->
val currentAppVer = versionCheckerUtils.versionDigits(config.get().VERSION_NAME)
val metadataVer = versionCheckerUtils.versionDigits(version.value)
if ((currentAppVer.size >= 2) && (metadataVer.size >= 2) && (abs(currentAppVer[1] - metadataVer[1]) > 1)) {
version.status = PrefsStatus.WARN
version.status = PrefsStatusImpl.WARN
version.info = rh.gs(R.string.metadata_warning_different_version)
}
if ((currentAppVer.isNotEmpty()) && (metadataVer.isNotEmpty()) && (currentAppVer[0] != metadataVer[0])) {
version.status = PrefsStatus.WARN
version.status = PrefsStatusImpl.WARN
version.info = rh.gs(R.string.metadata_urgent_different_version)
}
}

View file

@ -1,14 +1,13 @@
package info.nightscout.interfaces.maintenance
package info.nightscout.configuration.maintenance
import android.content.Context
import android.os.Parcelable
import androidx.annotation.DrawableRes
import androidx.annotation.StringRes
import info.nightscout.interfaces.R
import kotlinx.parcelize.Parcelize
import java.io.File
import info.nightscout.configuration.R
import info.nightscout.interfaces.maintenance.PrefsFormat
import info.nightscout.interfaces.maintenance.PrefsMetadataKey
enum class PrefsMetadataKey(val key: String, @DrawableRes val icon: Int, @StringRes val label: Int) {
enum class PrefsMetadataKeyImpl(override val key: String, @DrawableRes override val icon: Int, @StringRes override val label: Int) : PrefsMetadataKey {
FILE_FORMAT("format", R.drawable.ic_meta_format, R.string.metadata_label_format),
CREATED_AT("created_at", R.drawable.ic_meta_date, R.string.metadata_label_created_at),
@ -35,48 +34,16 @@ enum class PrefsMetadataKey(val key: String, @DrawableRes val icon: Int, @String
}
fun formatForDisplay(context: Context, value: String): String {
override fun formatForDisplay(context: Context, value: String): String {
return when (this) {
FILE_FORMAT -> when (value) {
PrefsFormat.FORMAT_KEY_ENC -> context.getString(R.string.metadata_format_new)
PrefsFormat.FORMAT_KEY_NOENC -> context.getString(R.string.metadata_format_debug)
else -> context.getString(R.string.metadata_format_other)
}
CREATED_AT -> value.replace("T", " ").replace("Z", " (UTC)")
else -> value
}
}
}
@Parcelize
data class PrefMetadata(var value: String, var status: PrefsStatus, var info: String? = null) : Parcelable
typealias PrefMetadataMap = Map<PrefsMetadataKey, PrefMetadata>
data class Prefs(val values: Map<String, String>, var metadata: PrefMetadataMap)
interface PrefsFormat {
companion object {
const val FORMAT_KEY_ENC = "aaps_encrypted"
const val FORMAT_KEY_NOENC = "aaps_structured"
}
fun savePreferences(file: File, prefs: Prefs, masterPassword: String? = null)
fun loadPreferences(file: File, masterPassword: String? = null): Prefs
fun loadMetadata(contents: String? = null): PrefMetadataMap
fun isPreferencesFile(file: File, preloadedContents: String? = null): Boolean
}
enum class PrefsStatus(@DrawableRes val icon: Int) {
OK(R.drawable.ic_meta_ok),
WARN(R.drawable.ic_meta_warning),
ERROR(R.drawable.ic_meta_error),
UNKNOWN(R.drawable.ic_meta_error),
DISABLED(R.drawable.ic_meta_error)
}
class PrefFileNotFoundError(message: String) : Exception(message)
class PrefIOError(message: String) : Exception(message)
class PrefFormatError(message: String) : Exception(message)

View file

@ -12,11 +12,11 @@ import info.nightscout.configuration.R
import info.nightscout.configuration.databinding.MaintenanceImportListActivityBinding
import info.nightscout.configuration.databinding.MaintenanceImportListItemBinding
import info.nightscout.configuration.maintenance.PrefsFileContract
import info.nightscout.configuration.maintenance.PrefsMetadataKeyImpl
import info.nightscout.core.ui.activities.TranslatedDaggerAppCompatActivity
import info.nightscout.interfaces.maintenance.PrefFileListProvider
import info.nightscout.interfaces.maintenance.PrefsFile
import info.nightscout.interfaces.maintenance.PrefsMetadataKey
import info.nightscout.interfaces.maintenance.PrefsStatus
import info.nightscout.interfaces.maintenance.PrefsStatusImpl
import info.nightscout.shared.interfaces.ResourceHelper
import javax.inject.Inject
@ -82,23 +82,23 @@ class PrefImportListActivity : TranslatedDaggerAppCompatActivity() {
metaDateTimeIcon.visibility = View.VISIBLE
metaAppVersion.visibility = View.VISIBLE
prefFile.metadata[PrefsMetadataKey.AAPS_FLAVOUR]?.let {
prefFile.metadata[PrefsMetadataKeyImpl.AAPS_FLAVOUR]?.let {
metaVariantFormat.text = it.value
val colorAttr = if (it.status == PrefsStatus.OK) info.nightscout.core.ui.R.attr.metadataTextOkColor else info.nightscout.core.ui.R.attr.metadataTextWarningColor
val colorAttr = if (it.status == PrefsStatusImpl.OK) info.nightscout.core.ui.R.attr.metadataTextOkColor else info.nightscout.core.ui.R.attr.metadataTextWarningColor
metaVariantFormat.setTextColor(rh.gac(metaVariantFormat.context, colorAttr))
}
prefFile.metadata[PrefsMetadataKey.CREATED_AT]?.let {
prefFile.metadata[PrefsMetadataKeyImpl.CREATED_AT]?.let {
metaDateTime.text = prefFileListProvider.formatExportedAgo(it.value)
}
prefFile.metadata[PrefsMetadataKey.AAPS_VERSION]?.let {
prefFile.metadata[PrefsMetadataKeyImpl.AAPS_VERSION]?.let {
metaAppVersion.text = it.value
val colorAttr = if (it.status == PrefsStatus.OK) info.nightscout.core.ui.R.attr.metadataTextOkColor else info.nightscout.core.ui.R.attr.metadataTextWarningColor
val colorAttr = if (it.status == PrefsStatusImpl.OK) info.nightscout.core.ui.R.attr.metadataTextOkColor else info.nightscout.core.ui.R.attr.metadataTextWarningColor
metaAppVersion.setTextColor(rh.gac(metaVariantFormat.context, colorAttr))
}
prefFile.metadata[PrefsMetadataKey.DEVICE_NAME]?.let {
prefFile.metadata[PrefsMetadataKeyImpl.DEVICE_NAME]?.let {
metaDeviceName.text = it.value
}

View file

@ -20,7 +20,7 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder
import info.nightscout.configuration.R
import info.nightscout.core.ui.toast.ToastUtils
import info.nightscout.interfaces.maintenance.Prefs
import info.nightscout.interfaces.maintenance.PrefsStatus
import info.nightscout.interfaces.maintenance.PrefsStatusImpl
import info.nightscout.shared.extensions.runOnUiThread
import java.util.LinkedList
@ -57,8 +57,8 @@ object PrefImportSummaryDialog {
(rowLayout.findViewById<View>(R.id.summary_icon) as ImageView).setImageResource(metaKey.icon)
(rowLayout.findViewById<View>(R.id.status_icon) as ImageView).setImageResource(metaEntry.status.icon)
if (metaEntry.status == PrefsStatus.WARN) label.setTextColor(themedCtx.getColor(info.nightscout.interfaces.R.color.metadataTextWarning))
else if (metaEntry.status == PrefsStatus.ERROR) label.setTextColor(themedCtx.getColor(info.nightscout.interfaces.R.color.metadataTextError))
if (metaEntry.status == PrefsStatusImpl.WARN) label.setTextColor(themedCtx.getColor(info.nightscout.interfaces.R.color.metadataTextWarning))
else if (metaEntry.status == PrefsStatusImpl.ERROR) label.setTextColor(themedCtx.getColor(info.nightscout.interfaces.R.color.metadataTextError))
if (metaEntry.info != null) {
details.add("<b>${context.getString(metaKey.label)}</b>: ${metaEntry.value}<br/><i style=\"color:silver\">${metaEntry.info}</i>")
@ -66,9 +66,9 @@ object PrefImportSummaryDialog {
rowLayout.setOnClickListener {
val msg = "[${context.getString(metaKey.label)}] ${metaEntry.info}"
when (metaEntry.status) {
PrefsStatus.WARN -> ToastUtils.Long.warnToast(context, msg)
PrefsStatus.ERROR -> ToastUtils.Long.errorToast(context, msg)
else -> ToastUtils.Long.infoToast(context, msg)
PrefsStatusImpl.WARN -> ToastUtils.Long.warnToast(context, msg)
PrefsStatusImpl.ERROR -> ToastUtils.Long.errorToast(context, msg)
else -> ToastUtils.Long.infoToast(context, msg)
}
}
} else {

View file

@ -1,6 +1,7 @@
package info.nightscout.configuration.maintenance.formats
import info.nightscout.configuration.R
import info.nightscout.configuration.maintenance.PrefsMetadataKeyImpl
import info.nightscout.core.utils.CryptoUtil
import info.nightscout.core.utils.hexStringToByteArray
import info.nightscout.core.utils.toHex
@ -13,6 +14,7 @@ import info.nightscout.interfaces.maintenance.Prefs
import info.nightscout.interfaces.maintenance.PrefsFormat
import info.nightscout.interfaces.maintenance.PrefsMetadataKey
import info.nightscout.interfaces.maintenance.PrefsStatus
import info.nightscout.interfaces.maintenance.PrefsStatusImpl
import info.nightscout.interfaces.storage.Storage
import info.nightscout.shared.interfaces.ResourceHelper
import org.json.JSONException
@ -59,8 +61,8 @@ class EncryptedPrefsFormat @Inject constructor(
val content = JSONObject()
val meta = JSONObject()
val encStatus = prefs.metadata[PrefsMetadataKey.ENCRYPTION]?.status ?: PrefsStatus.OK
var encrypted = encStatus == PrefsStatus.OK && masterPassword != null
val encStatus = prefs.metadata[PrefsMetadataKeyImpl.ENCRYPTION]?.status ?: PrefsStatusImpl.OK
var encrypted = encStatus == PrefsStatusImpl.OK && masterPassword != null
try {
for ((key, value) in prefs.values.toSortedMap()) {
@ -68,14 +70,14 @@ class EncryptedPrefsFormat @Inject constructor(
}
for ((metaKey, metaEntry) in prefs.metadata) {
if (metaKey == PrefsMetadataKey.FILE_FORMAT)
if (metaKey == PrefsMetadataKeyImpl.FILE_FORMAT)
continue
if (metaKey == PrefsMetadataKey.ENCRYPTION)
if (metaKey == PrefsMetadataKeyImpl.ENCRYPTION)
continue
meta.put(metaKey.key, metaEntry.value)
}
container.put(PrefsMetadataKey.FILE_FORMAT.key, if (encrypted) PrefsFormat.FORMAT_KEY_ENC else PrefsFormat.FORMAT_KEY_NOENC)
container.put(PrefsMetadataKeyImpl.FILE_FORMAT.key, if (encrypted) PrefsFormat.FORMAT_KEY_ENC else PrefsFormat.FORMAT_KEY_NOENC)
container.put("metadata", meta)
val security = JSONObject()
@ -130,22 +132,22 @@ class EncryptedPrefsFormat @Inject constructor(
val container = JSONObject(jsonBody)
val metadata: MutableMap<PrefsMetadataKey, PrefMetadata> = loadMetadata(container)
if (container.has(PrefsMetadataKey.FILE_FORMAT.key) && container.has("security") && container.has("content")) {
val fileFormat = container.getString(PrefsMetadataKey.FILE_FORMAT.key)
if (container.has(PrefsMetadataKeyImpl.FILE_FORMAT.key) && container.has("security") && container.has("content")) {
val fileFormat = container.getString(PrefsMetadataKeyImpl.FILE_FORMAT.key)
val security = container.getJSONObject("security")
val encrypted = fileFormat == PrefsFormat.FORMAT_KEY_ENC
var secure: PrefsStatus = PrefsStatus.OK
var secure: PrefsStatus = PrefsStatusImpl.OK
var decryptedOk = false
var contentJsonObj: JSONObject? = null
var insecurityReason = rh.gs(R.string.prefdecrypt_settings_tampered)
if (security.has("file_hash")) {
if (calculatedFileHash != security.getString("file_hash")) {
secure = PrefsStatus.ERROR
secure = PrefsStatusImpl.ERROR
issues.add(rh.gs(R.string.prefdecrypt_issue_modified))
}
} else {
secure = PrefsStatus.ERROR
secure = PrefsStatusImpl.ERROR
issues.add(rh.gs(R.string.prefdecrypt_issue_missing_file_hash))
}
@ -164,38 +166,38 @@ class EncryptedPrefsFormat @Inject constructor(
contentJsonObj = JSONObject(decrypted)
decryptedOk = true
} else {
secure = PrefsStatus.ERROR
secure = PrefsStatusImpl.ERROR
issues.add(rh.gs(R.string.prefdecrypt_issue_modified))
}
} catch (e: JSONException) {
secure = PrefsStatus.ERROR
secure = PrefsStatusImpl.ERROR
issues.add(rh.gs(R.string.prefdecrypt_issue_parsing))
}
} else {
secure = PrefsStatus.ERROR
secure = PrefsStatusImpl.ERROR
issues.add(rh.gs(R.string.prefdecrypt_issue_wrong_pass))
insecurityReason = rh.gs(R.string.prefdecrypt_wrong_password)
}
} else {
secure = PrefsStatus.ERROR
secure = PrefsStatusImpl.ERROR
issues.add(rh.gs(R.string.prefdecrypt_issue_wrong_format))
}
} else {
secure = PrefsStatus.ERROR
secure = PrefsStatusImpl.ERROR
issues.add(rh.gs(R.string.prefdecrypt_issue_wrong_algorithm))
}
} else {
if (secure == PrefsStatus.OK) {
secure = PrefsStatus.WARN
if (secure == PrefsStatusImpl.OK) {
secure = PrefsStatusImpl.WARN
}
if (!(security.has("algorithm") && security.get("algorithm") == "none")) {
secure = PrefsStatus.ERROR
secure = PrefsStatusImpl.ERROR
issues.add(rh.gs(R.string.prefdecrypt_issue_wrong_algorithm))
}
@ -211,12 +213,12 @@ class EncryptedPrefsFormat @Inject constructor(
val issuesStr: String? = if (issues.size > 0) issues.joinToString("\n") else null
val encryptionDescStr = if (encrypted) {
if (secure == PrefsStatus.OK) rh.gs(R.string.prefdecrypt_settings_secure) else insecurityReason
if (secure == PrefsStatusImpl.OK) rh.gs(R.string.prefdecrypt_settings_secure) else insecurityReason
} else {
if (secure != PrefsStatus.ERROR) rh.gs(R.string.prefdecrypt_settings_unencrypted) else rh.gs(R.string.prefdecrypt_settings_tampered)
if (secure != PrefsStatusImpl.ERROR) rh.gs(R.string.prefdecrypt_settings_unencrypted) else rh.gs(R.string.prefdecrypt_settings_tampered)
}
metadata[PrefsMetadataKey.ENCRYPTION] = PrefMetadata(encryptionDescStr, secure, issuesStr)
metadata[PrefsMetadataKeyImpl.ENCRYPTION] = PrefMetadata(encryptionDescStr, secure, issuesStr)
}
return Prefs(entries, metadata)
@ -243,22 +245,22 @@ class EncryptedPrefsFormat @Inject constructor(
private fun loadMetadata(container: JSONObject): MutableMap<PrefsMetadataKey, PrefMetadata> {
val metadata: MutableMap<PrefsMetadataKey, PrefMetadata> = mutableMapOf()
if (container.has(PrefsMetadataKey.FILE_FORMAT.key) && container.has("security") && container.has("content") && container.has("metadata")) {
val fileFormat = container.getString(PrefsMetadataKey.FILE_FORMAT.key)
if (container.has(PrefsMetadataKeyImpl.FILE_FORMAT.key) && container.has("security") && container.has("content") && container.has("metadata")) {
val fileFormat = container.getString(PrefsMetadataKeyImpl.FILE_FORMAT.key)
if ((fileFormat != PrefsFormat.FORMAT_KEY_ENC) && (fileFormat != PrefsFormat.FORMAT_KEY_NOENC)) {
metadata[PrefsMetadataKey.FILE_FORMAT] = PrefMetadata(rh.gs(info.nightscout.interfaces.R.string.metadata_format_other), PrefsStatus.ERROR)
metadata[PrefsMetadataKeyImpl.FILE_FORMAT] = PrefMetadata(rh.gs(R.string.metadata_format_other), PrefsStatusImpl.ERROR)
} else {
val meta = container.getJSONObject("metadata")
metadata[PrefsMetadataKey.FILE_FORMAT] = PrefMetadata(fileFormat, PrefsStatus.OK)
metadata[PrefsMetadataKeyImpl.FILE_FORMAT] = PrefMetadata(fileFormat, PrefsStatusImpl.OK)
for (key in meta.keys()) {
val metaKey = PrefsMetadataKey.fromKey(key)
val metaKey = PrefsMetadataKeyImpl.fromKey(key)
if (metaKey != null) {
metadata[metaKey] = PrefMetadata(meta.getString(key), PrefsStatus.OK)
metadata[metaKey] = PrefMetadata(meta.getString(key), PrefsStatusImpl.OK)
}
}
}
} else {
metadata[PrefsMetadataKey.FILE_FORMAT] = PrefMetadata(rh.gs(R.string.prefdecrypt_wrong_json), PrefsStatus.ERROR)
metadata[PrefsMetadataKeyImpl.FILE_FORMAT] = PrefMetadata(rh.gs(R.string.prefdecrypt_wrong_json), PrefsStatusImpl.ERROR)
}
return metadata

View file

@ -0,0 +1,37 @@
package info.nightscout.interfaces.maintenance
import androidx.annotation.DrawableRes
import info.nightscout.configuration.R
import kotlinx.parcelize.Parcelize
import java.io.File
typealias PrefMetadataMap = Map<PrefsMetadataKey, PrefMetadata>
data class Prefs(val values: Map<String, String>, var metadata: PrefMetadataMap)
interface PrefsFormat {
companion object {
const val FORMAT_KEY_ENC = "aaps_encrypted"
const val FORMAT_KEY_NOENC = "aaps_structured"
}
fun savePreferences(file: File, prefs: Prefs, masterPassword: String? = null)
fun loadPreferences(file: File, masterPassword: String? = null): Prefs
fun loadMetadata(contents: String? = null): PrefMetadataMap
fun isPreferencesFile(file: File, preloadedContents: String? = null): Boolean
}
@Parcelize
enum class PrefsStatusImpl(@DrawableRes override val icon: Int) : PrefsStatus {
OK(R.drawable.ic_meta_ok),
WARN(R.drawable.ic_meta_warning),
ERROR(R.drawable.ic_meta_error),
UNKNOWN(R.drawable.ic_meta_error),
DISABLED(R.drawable.ic_meta_error)
}
class PrefFileNotFoundError(message: String) : Exception(message)
class PrefIOError(message: String) : Exception(message)
class PrefFormatError(message: String) : Exception(message)

View file

@ -170,4 +170,16 @@
<!-- Permissions -->
<string name="alert_dialog_storage_permission_text">Please reboot your phone or restart AAPS from the System Settings \notherwise Android APS will not have logging (important to track and verify that the algorithms are working correctly)!</string>
<!-- Maintenance -->
<string name="metadata_label_format">File format</string>
<string name="metadata_label_created_at">Created at</string>
<string name="metadata_label_aaps_version">AAPS Version</string>
<string name="metadata_label_aaps_flavour">Build Variant</string>
<string name="metadata_label_device_name">Exporting device patient name</string>
<string name="metadata_label_device_model">Exporting device model</string>
<string name="metadata_label_encryption">File encryption</string>
<string name="metadata_format_new">New encrypted format</string>
<string name="metadata_format_debug">New debug format (unencrypted)</string>
<string name="metadata_format_other">Unknown export format</string>
</resources>

View file

@ -120,7 +120,7 @@ class TreatmentsUserEntryFragment : DaggerFragment(), MenuProvider {
_binding = null
}
inner class UserEntryAdapter internal constructor(var entries: List<UserEntry>) : RecyclerView.Adapter<UserEntryAdapter.UserEntryViewHolder>() {
inner class UserEntryAdapter internal constructor(private var entries: List<UserEntry>) : RecyclerView.Adapter<UserEntryAdapter.UserEntryViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): UserEntryViewHolder {
val view: View = LayoutInflater.from(parent.context).inflate(R.layout.treatments_user_entry_item, parent, false)