Skip to content

Commit

Permalink
A11 file scoped acess
Browse files Browse the repository at this point in the history
  • Loading branch information
MilosKozak committed Nov 8, 2024
1 parent d9988f1 commit 4626bd7
Show file tree
Hide file tree
Showing 47 changed files with 258 additions and 192 deletions.
11 changes: 4 additions & 7 deletions app/src/main/kotlin/app/aaps/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,6 @@ import app.aaps.core.interfaces.ui.UiInteraction
import app.aaps.core.interfaces.utils.fabric.FabricPrivacy
import app.aaps.core.interfaces.versionChecker.VersionCheckerUtils
import app.aaps.core.keys.BooleanKey
import app.aaps.core.keys.Preferences
import app.aaps.core.keys.StringKey
import app.aaps.core.objects.crypto.CryptoUtil
import app.aaps.core.ui.UIRunnable
Expand All @@ -82,7 +81,6 @@ import com.joanzapata.iconify.Iconify
import com.joanzapata.iconify.fonts.FontAwesomeModule
import io.reactivex.rxjava3.disposables.CompositeDisposable
import io.reactivex.rxjava3.kotlin.plusAssign
import java.io.File
import java.util.Locale
import javax.inject.Inject
import kotlin.system.exitProcess
Expand All @@ -94,7 +92,6 @@ class MainActivity : DaggerAppCompatActivityWithResult() {
@Inject lateinit var aapsSchedulers: AapsSchedulers
@Inject lateinit var androidPermission: AndroidPermission
@Inject lateinit var sp: SP
@Inject lateinit var preferences: Preferences
@Inject lateinit var versionCheckerUtils: VersionCheckerUtils
@Inject lateinit var smsCommunicator: SmsCommunicator
@Inject lateinit var loop: Loop
Expand Down Expand Up @@ -486,8 +483,8 @@ class MainActivity : DaggerAppCompatActivityWithResult() {
* reset password to SN of active pump if file exists
*/
private fun passwordResetCheck(context: Context) {
val fh = File(fileListProvider.ensureExtraDirExists(), "PasswordReset")
if (fh.exists()) {
val fh = fileListProvider.ensureExtraDirExists()?.findFile("PasswordReset")
if (fh?.exists() == true) {
val sn = activePlugin.activePump.serialNumber()
preferences.put(StringKey.ProtectionMasterPassword, cryptoUtil.hashPassword(sn))
fh.delete()
Expand All @@ -502,8 +499,8 @@ class MainActivity : DaggerAppCompatActivityWithResult() {
* clear password stored in datastore if file exists
*/
private fun exportPasswordResetCheck(context: Context) {
val fh = File(fileListProvider.ensureExtraDirExists(), "ExportPasswordReset")
if (fh.exists()) {
val fh = fileListProvider.ensureExtraDirExists()?.findFile("ExportPasswordReset")
if (fh?.exists() == true) {
exportPasswordDataStore.clearPasswordDataStore(context)
fh.delete()
ToastUtils.okToast(context, context.getString(app.aaps.core.ui.R.string.datastore_password_cleared))
Expand Down
34 changes: 8 additions & 26 deletions app/src/main/kotlin/app/aaps/implementations/ConfigImpl.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,12 @@ import app.aaps.R
import app.aaps.core.interfaces.configuration.Config
import app.aaps.core.interfaces.maintenance.FileListProvider
import dagger.Reusable
import java.io.File
import javax.inject.Inject

@Suppress("KotlinConstantConditions")
@Reusable
class ConfigImpl @Inject constructor(
fileListProvider: FileListProvider
private val fileListProvider: FileListProvider
) : Config {

override val SUPPORTED_NS_VERSION = 150000 // 15.0.0
Expand All @@ -31,33 +30,16 @@ class ConfigImpl @Inject constructor(
override val APPLICATION_ID: String = BuildConfig.APPLICATION_ID
override val DEBUG = BuildConfig.DEBUG

override val currentDeviceModelString =
Build.MANUFACTURER + " " + Build.MODEL + " (" + Build.DEVICE + ")"
override val currentDeviceModelString = Build.MANUFACTURER + " " + Build.MODEL + " (" + Build.DEVICE + ")"
override val appName: Int = R.string.app_name

override var appInitialized: Boolean = false

private var devBranch = false
private var engineeringMode = false
private var unfinishedMode = false
private var isEngineeringMode: Boolean? = null
private var isUnfinishedMode: Boolean? = null

init {
val engineeringModeSemaphore = File(fileListProvider.ensureExtraDirExists(), "engineering_mode")
val unfinishedModeSemaphore = File(fileListProvider.ensureExtraDirExists(), "unfinished_mode")

engineeringMode = engineeringModeSemaphore.exists() && engineeringModeSemaphore.isFile
unfinishedMode = unfinishedModeSemaphore.exists() && unfinishedModeSemaphore.isFile
devBranch = VERSION.contains("-") || VERSION.matches(Regex(".*[a-zA-Z]+.*"))
if (VERSION.contains("-beta") || VERSION.contains("-rc"))
devBranch = false
}

override fun isEngineeringModeOrRelease(): Boolean =
if (!APS) true else engineeringMode || !devBranch

override fun isEngineeringMode(): Boolean = engineeringMode

override fun isUnfinishedMode(): Boolean = unfinishedMode

override fun isDev(): Boolean = devBranch
override fun isEngineeringModeOrRelease(): Boolean = if (!APS) true else isEngineeringMode() || !isDev()
override fun isEngineeringMode(): Boolean = isEngineeringMode ?: (fileListProvider.ensureExtraDirExists()?.findFile("engineering_mode") != null).also { isEngineeringMode = it }
override fun isUnfinishedMode(): Boolean = isUnfinishedMode ?: (fileListProvider.ensureExtraDirExists()?.findFile("unfinished_mode") != null).also { isUnfinishedMode = it }
override fun isDev(): Boolean = (VERSION.contains("-") || VERSION.matches(Regex(".*[a-zA-Z]+.*"))) && !VERSION.contains("-beta") && !VERSION.contains("-rc")
}
1 change: 1 addition & 0 deletions core/data/src/main/kotlin/app/aaps/core/data/ue/Action.kt
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ enum class Action(val colorGroup: ColorGroup) {
DELETE_FUTURE_TREATMENTS(ColorGroup.Aaps),
EXPORT_SETTINGS(ColorGroup.Aaps),
IMPORT_SETTINGS(ColorGroup.Aaps),
SELECT_DIRECTORY(ColorGroup.Aaps),
RESET_DATABASES(ColorGroup.Aaps),
RESET_APS_RESULTS(ColorGroup.Aaps),
CLEANUP_DATABASES(ColorGroup.Aaps),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,23 @@
package app.aaps.core.interfaces.maintenance

import androidx.documentfile.provider.DocumentFile
import app.aaps.core.interfaces.rx.weardata.CwfFile
import java.io.File

interface FileListProvider {

val resultPath: File
fun ensureTempDirExists(): File
fun ensureExportDirExists(): File
fun ensureExtraDirExists(): File
fun ensurePreferenceDirExists(): DocumentFile?
fun ensureExportDirExists(): DocumentFile?
fun ensureTempDirExists(): DocumentFile?
fun ensureExtraDirExists(): DocumentFile?

fun newPreferenceFile(): DocumentFile?
fun newExportCsvFile(): DocumentFile?
fun newCwfFile(filename: String, withDate: Boolean = true): DocumentFile?

fun ensureResultDirExists(): File
fun newExportFile(): File
fun newExportCsvFile(): File
fun newResultFile(): File
fun newCwfFile(filename: String, withDate: Boolean = true): File
fun listPreferenceFiles(): MutableList<PrefsFile>
fun listCustomWatchfaceFiles(): MutableList<CwfFile>
fun checkMetadata(metadata: Map<PrefsMetadataKey, PrefMetadata>): Map<PrefsMetadataKey, PrefMetadata>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,11 @@ package app.aaps.core.interfaces.maintenance
import android.os.Parcelable
import kotlinx.parcelize.Parcelize
import kotlinx.parcelize.RawValue
import java.io.File

@Parcelize
data class PrefsFile(
val name: String,
val file: File,
val baseDir: File,
val content: String,

// metadata here is used only for list display
val metadata: @RawValue Map<PrefsMetadataKey, PrefMetadata>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ abstract class PluginBase(
}

fun showInList(type: PluginType): Boolean {
if (pluginDescription.mainType == type) return pluginDescription.showInList && specialShowInListCondition()
if (pluginDescription.mainType == type) return pluginDescription.showInList.invoke() && specialShowInListCondition()
return false
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ open class PluginDescription {
var alwaysVisible = false
var neverVisible = false
var alwaysEnabled = false
var showInList = true
var showInList = { true }
var pluginName = -1
var shortName = -1
var description = -1
Expand All @@ -42,7 +42,7 @@ open class PluginDescription {
fun alwaysEnabled(alwaysEnabled: Boolean): PluginDescription = this.also { it.alwaysEnabled = alwaysEnabled }
fun alwaysVisible(alwaysVisible: Boolean): PluginDescription = this.also { it.alwaysVisible = alwaysVisible }
fun neverVisible(neverVisible: Boolean): PluginDescription = this.also { it.neverVisible = neverVisible }
fun showInList(showInList: Boolean): PluginDescription = this.also { it.showInList = showInList }
fun showInList(showInList: () -> Boolean): PluginDescription = this.also { it.showInList = showInList }
fun pluginIcon(pluginIcon: Int): PluginDescription = this.also { it.pluginIcon = pluginIcon }
fun pluginIcon2(pluginIcon2: Int): PluginDescription = this.also { it.pluginIcon2 = pluginIcon2 }
fun pluginName(pluginName: Int): PluginDescription = this.also { it.pluginName = pluginName }
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
package app.aaps.core.interfaces.storage

import android.content.ContentResolver
import androidx.documentfile.provider.DocumentFile
import java.io.File

// This may seems unnecessary abstraction - but it will simplify testing
interface Storage {

fun getFileContents(file: File): String
fun putFileContents(file: File, contents: String)

fun putFileContents(contentResolver: ContentResolver, file: DocumentFile, contents: String)
fun getFileContents(file: File): String
fun getFileContents(contentResolver: ContentResolver, file: DocumentFile): String
fun getBinaryFileContents(contentResolver: ContentResolver, file: DocumentFile): ByteArray?
}
2 changes: 2 additions & 0 deletions core/keys/src/main/kotlin/app/aaps/core/keys/StringKey.kt
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ enum class StringKey(
GeneralSkin("skin", ""),
GeneralDarkMode("use_dark_mode", "dark", defaultedBySM = true),

AapsDirectoryUri("aaps_directory", ""),

ProtectionMasterPassword("master_password", "", isPassword = true),
ProtectionSettingsPassword("settings_password", "", isPassword = true),
ProtectionSettingsPin("settings_pin", "", isPin = true),
Expand Down
5 changes: 5 additions & 0 deletions core/ui/src/main/res/drawable/ic_directory.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="48dp" android:tint="#FFFFFF" android:viewportHeight="24" android:viewportWidth="24" android:width="48dp">

<path android:fillColor="@android:color/white" android:pathData="M20,6h-8l-2,-2H4C2.9,4 2,4.9 2,6v12c0,1.1 0.9,2 2,2h16c1.1,0 2,-0.9 2,-2V8C22,6.9 21.1,6 20,6zM12,17l-4,-4l4,-4v3h4v2h-4V17z"/>

</vector>
1 change: 1 addition & 0 deletions core/ui/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,7 @@
<string name="delete_future_treatments">Delete future treatments</string>
<string name="uel_export_settings">EXPORT SETTINGS</string>
<string name="uel_import_settings">IMPORT SETTINGS</string>
<string name="uel_select_directory">SELECT DIRECTORY</string>
<string name="uel_reset_databases">RESET DATABASES</string>
<string name="uel_reset_aps_results">RESET APS RESULTS</string>
<string name="uel_cleanup_databases">CLEANUP DATABASES</string>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ data class UserEntry(
DELETE_FUTURE_TREATMENTS,
EXPORT_SETTINGS,
IMPORT_SETTINGS,
SELECT_DIRECTORY,
RESET_DATABASES,
RESET_APS_RESULTS,
CLEANUP_DATABASES,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ fun UserEntry.Action.fromDb(): Action =
UserEntry.Action.DELETE_FUTURE_TREATMENTS -> Action.DELETE_FUTURE_TREATMENTS
UserEntry.Action.EXPORT_SETTINGS -> Action.EXPORT_SETTINGS
UserEntry.Action.IMPORT_SETTINGS -> Action.IMPORT_SETTINGS
UserEntry.Action.SELECT_DIRECTORY -> Action.SELECT_DIRECTORY
UserEntry.Action.RESET_DATABASES -> Action.RESET_DATABASES
UserEntry.Action.RESET_APS_RESULTS -> Action.RESET_APS_RESULTS
UserEntry.Action.CLEANUP_DATABASES -> Action.CLEANUP_DATABASES
Expand Down Expand Up @@ -168,6 +169,7 @@ fun Action.toDb(): UserEntry.Action =
Action.DELETE_FUTURE_TREATMENTS -> UserEntry.Action.DELETE_FUTURE_TREATMENTS
Action.EXPORT_SETTINGS -> UserEntry.Action.EXPORT_SETTINGS
Action.IMPORT_SETTINGS -> UserEntry.Action.IMPORT_SETTINGS
Action.SELECT_DIRECTORY -> UserEntry.Action.SELECT_DIRECTORY
Action.RESET_DATABASES -> UserEntry.Action.RESET_DATABASES
Action.RESET_APS_RESULTS -> UserEntry.Action.RESET_APS_RESULTS
Action.CLEANUP_DATABASES -> UserEntry.Action.CLEANUP_DATABASES
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import javax.inject.Inject
@Reusable
class LoggerUtilsImpl @Inject constructor() : LoggerUtils {

override var suffix = ".log.zip"
override var suffix = ".log"

/**
* Returns the directory, in which the logs are stored on the system. This is configured in the
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import app.aaps.core.interfaces.sharedPreferences.SP
import app.aaps.core.interfaces.utils.DateUtil
import app.aaps.core.keys.BooleanKey
import kotlinx.coroutines.runBlocking
import java.io.File
import javax.inject.Inject
import javax.inject.Singleton

Expand All @@ -33,7 +32,7 @@ import javax.inject.Singleton
* - The actual password is not stored, only a secret "key" containing encrypted data and parameters.
* - The secret "key" is used for secure access to the password in the "Android KeyStore"
*
* Dependancy: Class SecureEncrypt
* Dependency: Class SecureEncrypt
*
*/

Expand Down Expand Up @@ -100,8 +99,8 @@ class ExportPasswordDataStoreImpl @Inject constructor(
// START
if (config.isEngineeringMode() && config.isDev()) {
// Enable debug mode when file 'DebugUnattendedExport' exists
val debug = File(fileListProvider.ensureExtraDirExists(), "DebugUnattendedExport").exists()
val debugDev = File(fileListProvider.ensureExtraDirExists(), "DebugUnattendedExportDev").exists()
val debug = fileListProvider.ensureExtraDirExists()?.findFile("DebugUnattendedExport") != null
val debugDev = fileListProvider.ensureExtraDirExists()?.findFile("DebugUnattendedExportDev") != null
if (debugDev) {
log.warn(LTag.CORE, "$MODULE: ExportPasswordDataStore running DEBUG(DEV) mode!")
/*** Debug/testing mode ***/
Expand All @@ -111,13 +110,13 @@ class ExportPasswordDataStoreImpl @Inject constructor(
else if (debug) {
log.warn(LTag.CORE, "$MODULE: ExportPasswordDataStore running DEBUG mode!")
/*** Debug mode ***/
passwordValidityWindow = 2 * 24 * 3600 * 1000L // 2 Days (including grace periodee)
passwordValidityWindow = 2 * 24 * 3600 * 1000L // 2 Days (including grace period)
passwordExpiryGracePeriod = passwordValidityWindow/2 // Grace period 1 days
}
}
// END

log.info(LTag.CORE, "$MODULE: ExportPasswordDataStore is enabled: $exportPasswordStoreIsEnabled, expiry msecs=$passwordValidityWindow")
log.info(LTag.CORE, "$MODULE: ExportPasswordDataStore is enabled: $exportPasswordStoreIsEnabled, expiry millis=$passwordValidityWindow")
return exportPasswordStoreIsEnabled
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
package app.aaps.implementation.storage

import android.content.ContentResolver
import androidx.documentfile.provider.DocumentFile
import app.aaps.core.interfaces.storage.Storage
import java.io.BufferedReader
import java.io.File
import java.io.FileOutputStream
import java.io.InputStreamReader
import javax.inject.Inject
import javax.inject.Singleton

Expand All @@ -12,8 +17,28 @@ class FileStorage @Inject constructor() : Storage {
return file.readText()
}

override fun getFileContents(contentResolver: ContentResolver, file: DocumentFile): String {
val inputStream = contentResolver.openInputStream(file.uri)
val reader = BufferedReader(InputStreamReader(inputStream))
return reader.readText()
}

override fun getBinaryFileContents(contentResolver: ContentResolver, file: DocumentFile): ByteArray? {
val inputStream = contentResolver.openInputStream(file.uri)
val byteArray = inputStream?.readBytes()
inputStream?.close()
return byteArray
}

override fun putFileContents(file: File, contents: String) {
file.writeText(contents)
}

override fun putFileContents(contentResolver: ContentResolver, file: DocumentFile, contents: String) {
val output = FileOutputStream(contentResolver.openFileDescriptor(file.uri, "w")?.fileDescriptor)
output.write(contents.toByteArray())
output.flush()
output.close()
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ class TranslatorImpl @Inject internal constructor(
Action.DELETE_FUTURE_TREATMENTS -> rh.gs(R.string.uel_delete_future_treatments)
Action.EXPORT_SETTINGS -> rh.gs(R.string.uel_export_settings)
Action.IMPORT_SETTINGS -> rh.gs(R.string.uel_import_settings)
Action.SELECT_DIRECTORY -> rh.gs(R.string.uel_select_directory)
Action.RESET_DATABASES -> rh.gs(R.string.uel_reset_databases)
Action.RESET_APS_RESULTS -> rh.gs(R.string.uel_reset_aps_results)
Action.CLEANUP_DATABASES -> rh.gs(R.string.uel_cleanup_databases)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ class AutotunePlugin @Inject constructor(
.pluginName(app.aaps.core.ui.R.string.autotune)
.shortName(R.string.autotune_shortname)
.preferencesId(PluginDescription.PREFERENCE_SCREEN)
.showInList(config.isEngineeringMode() && config.isDev())
.showInList({ config.isEngineeringMode() && config.isDev() })
.description(R.string.autotune_description),
aapsLogger, resourceHelper
), Autotune {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ class OpenAPSAMAPlugin @Inject constructor(
.shortName(R.string.oaps_shortname)
.preferencesId(PluginDescription.PREFERENCE_SCREEN)
.preferencesVisibleInSimpleMode(false)
.showInList(config.APS)
.showInList({ config.APS })
.description(R.string.description_ama),
aapsLogger, rh
), APS, PluginConstraints {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ open class OpenAPSAutoISFPlugin @Inject constructor(
.shortName(R.string.autoisf_shortname)
.preferencesId(PluginDescription.PREFERENCE_SCREEN)
.preferencesVisibleInSimpleMode(false)
.showInList(config.isEngineeringMode() && config.isDev())
.showInList({ config.isEngineeringMode() && config.isDev() })
.description(R.string.description_auto_isf),
aapsLogger, rh
), APS, PluginConstraints {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ open class OpenAPSSMBPlugin @Inject constructor(
.shortName(app.aaps.core.ui.R.string.smb_shortname)
.preferencesId(PluginDescription.PREFERENCE_SCREEN)
.preferencesVisibleInSimpleMode(false)
.showInList(config.APS)
.showInList({ config.APS })
.description(R.string.description_smb)
.setDefault(),
aapsLogger, rh
Expand Down
Loading

1 comment on commit 4626bd7

@vanelsberg
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good! 👍
Tested on Android 14 (S22 Ultra) and Android 12 (Nokia 5.4).

  • /AAPS/test
  • /Documents/AAPStest
    New and switching for one to the other works.

Tests need validating as this commit breaks FullDebug build.

No ussies found, all well!
Imho, ready for merge with dev.

Please sign in to comment.