aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.github/ISSUE_TEMPLATE/bug_report.yaml8
-rw-r--r--.github/ISSUE_TEMPLATE/feature_request.yaml2
-rw-r--r--CHANGELOG.md5
-rw-r--r--app/src/main/java/app/passwordstore/ui/settings/SettingsDestination.kt13
-rw-r--r--app/src/main/java/app/passwordstore/ui/settings/SettingsGraph.kt3
-rw-r--r--app/src/main/java/app/passwordstore/ui/settings/SettingsModel.kt15
-rw-r--r--app/src/main/java/app/passwordstore/ui/settings/SettingsScreen.kt6
-rw-r--r--app/src/main/java/app/passwordstore/ui/settings/SettingsViewModel.kt28
-rw-r--r--app/src/main/res/values-it/strings.xml4
-rw-r--r--app/src/main/res/values/strings.xml4
10 files changed, 82 insertions, 6 deletions
diff --git a/.github/ISSUE_TEMPLATE/bug_report.yaml b/.github/ISSUE_TEMPLATE/bug_report.yaml
index 0954037d..76d59e7b 100644
--- a/.github/ISSUE_TEMPLATE/bug_report.yaml
+++ b/.github/ISSUE_TEMPLATE/bug_report.yaml
@@ -7,10 +7,10 @@ body:
attributes:
value: |
Thanks for taking the time to file this issue! Here are a few things to check before clicking the submit button :)
- 1. Make sure you're on the latest version of the app. The current release can be found here: https://github.com/android-password-store/android-password-store/releases/latest.
- 2. Search through **both** open and closed issues for your bug: https://github.com/android-password-store/Android-Password-Store/issues?q=is%3Aissue+sort%3Aupdated-desc+.
+ 1. Make sure you're on the latest version of the app. The current release can be found here: https://github.com/danixland/HardenedPass/releases/latest.
+ 2. Search through **both** open and closed issues for your bug: https://github.com/danixland/HardenedPass/issues?q=is%3Aissue+sort%3Aupdated-desc+.
3. ALWAYS fill this template. If you fail to do so, your issue will be immediately closed with no response. Maintaining open source projects for free is hard work, and we expect users to respect that time and effort by putting in a little bit of their own. That helps us fix these problems faster and in return you get a better app — everybody wins.
- 4. Please record a device log, and attach it to the issue. You can follow the steps here for it: https://docs.passwordstore.app/docs/users/reporting-bugs
+ 4. Please attach a log: turn on Settings > Misc > Debug logging, restart the app, reproduce the bug, then use Settings > Misc > Export log. Read the file first and remove anything you do not want public: it can show entry names, websites, apps and your git server.
- type: textarea
id: bug-description
@@ -58,7 +58,7 @@ body:
value: |
- Device: [e.g. Google Pixel 2]
- OS: [e.g. Android R]
- - App version: [e.g. 1.13.5]
+ - App version: [e.g. 0.3.2]
validations:
required: true
diff --git a/.github/ISSUE_TEMPLATE/feature_request.yaml b/.github/ISSUE_TEMPLATE/feature_request.yaml
index 7e075dcc..f252cd29 100644
--- a/.github/ISSUE_TEMPLATE/feature_request.yaml
+++ b/.github/ISSUE_TEMPLATE/feature_request.yaml
@@ -7,7 +7,7 @@ body:
attributes:
value: |
Thanks for taking the time to file this issue! Here are a few things to check before clicking the submit button :)
- 1. Make sure you're on the latest version of the app. Features are being added all the time and it is entirely possible what you're requesting has already been added. The current release can be found here: https://github.com/android-password-store/android-password-store/releases/latest.
+ 1. Make sure you're on the latest version of the app. Features are being added all the time and it is entirely possible what you're requesting has already been added. The current release can be found here: https://github.com/danixland/HardenedPass/releases/latest.
2. Check the changelog file to confirm that the feature hasn't been added for an upcoming release: https://github.com/danixland/HardenedPass/blob/master/CHANGELOG.md
3. ALWAYS fill this template. If you fail to do so, your issue will be immediately closed with no response. Maintaining open source projects for free is hard work, and we expect users to respect that time and effort by putting in a little bit of their own. A feature request that is clear and explicit in its needs lets us get to work faster.
diff --git a/CHANGELOG.md b/CHANGELOG.md
index e33382c9..ffea326e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,6 +7,11 @@ All notable changes to this project will be documented in this file.
### Added
- A "Push after each change" setting, off by default, pushes after saving, moving or deleting in the app; autofill saves stay local until the next push or sync
+- Settings, Misc: "Export log" saves the app's logs to a file you choose, to attach to a bug report
+
+### Changed
+
+- Debug logs no longer show entry names from commits and autofill matches, or form fields' HTML attributes other than id, name, type, autocomplete and maxlength
### Fixed
diff --git a/app/src/main/java/app/passwordstore/ui/settings/SettingsDestination.kt b/app/src/main/java/app/passwordstore/ui/settings/SettingsDestination.kt
index c3809b36..05dc6b65 100644
--- a/app/src/main/java/app/passwordstore/ui/settings/SettingsDestination.kt
+++ b/app/src/main/java/app/passwordstore/ui/settings/SettingsDestination.kt
@@ -38,6 +38,7 @@ import androidx.core.net.toUri
import androidx.documentfile.provider.DocumentFile
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.compose.LifecycleResumeEffect
+import androidx.lifecycle.lifecycleScope
import app.passwordstore.BuildConfig
import app.passwordstore.R
import app.passwordstore.ui.compose.theme.SpacingLarge
@@ -52,6 +53,7 @@ import app.passwordstore.util.services.PasswordExportService
import app.passwordstore.util.settings.PreferenceKeys
import com.github.androidpasswordstore.autofillparser.BrowserAutofillSupportLevel
import com.github.androidpasswordstore.autofillparser.getInstalledBrowsersWithAutofillSupportLevel
+import kotlinx.coroutines.launch
private enum class SettingsDialog {
Autofill,
@@ -125,6 +127,16 @@ fun SettingsSectionDestination(
)
}
+ val exportLog =
+ rememberLauncherForActivityResult(ActivityResultContracts.CreateDocument("text/plain")) { uri ->
+ if (uri != null)
+ activity.lifecycleScope.launch {
+ val message =
+ if (viewModel.exportLog(uri)) R.string.log_exported else R.string.log_export_failed
+ activity.snackbar(message = activity.getString(message))
+ }
+ }
+
// One screen lock prompt at a time: a double tap must not open two. A recreation resets it
// (remember), and the old activity's prompt is gone with it.
var prompting by remember { mutableStateOf(false) }
@@ -206,6 +218,7 @@ fun SettingsSectionDestination(
SettingsAction.ClearSecret -> dialog = SettingsDialog.ClearSecret
SettingsAction.DeleteRepository -> dialog = SettingsDialog.DeleteRepository
SettingsAction.Export -> export.launch(null)
+ SettingsAction.ExportLog -> exportLog.launch("hardenedpass-log.txt")
else -> onOpen(action)
}
},
diff --git a/app/src/main/java/app/passwordstore/ui/settings/SettingsGraph.kt b/app/src/main/java/app/passwordstore/ui/settings/SettingsGraph.kt
index ba4d158c..e45166e0 100644
--- a/app/src/main/java/app/passwordstore/ui/settings/SettingsGraph.kt
+++ b/app/src/main/java/app/passwordstore/ui/settings/SettingsGraph.kt
@@ -70,7 +70,8 @@ fun NavGraphBuilder.settingsGraph(activity: MainActivity, nav: NavHostController
// Handled by the destination itself.
SettingsAction.ClearSecret,
SettingsAction.DeleteRepository,
- SettingsAction.Export -> Unit
+ SettingsAction.Export,
+ SettingsAction.ExportLog -> Unit
}
},
onDeleted = {
diff --git a/app/src/main/java/app/passwordstore/ui/settings/SettingsModel.kt b/app/src/main/java/app/passwordstore/ui/settings/SettingsModel.kt
index eca6770c..54250f74 100644
--- a/app/src/main/java/app/passwordstore/ui/settings/SettingsModel.kt
+++ b/app/src/main/java/app/passwordstore/ui/settings/SettingsModel.kt
@@ -9,6 +9,7 @@ import app.passwordstore.util.extensions.hash
import app.passwordstore.util.extensions.time
import app.passwordstore.util.git.GitCommit
import java.io.IOException
+import java.io.OutputStream
import logcat.LogPriority.ERROR
import logcat.asLog
import logcat.logcat
@@ -77,3 +78,17 @@ fun gitLog(repo: Repository?): List<GitCommit> {
emptyList()
}
}
+
+/**
+ * Writes [header], then what logcat holds for this app: Android shows an app only its own lines,
+ * and those of its earlier runs and crashes until the buffer rotates.
+ */
+fun writeAppLog(header: String, out: OutputStream) {
+ out.write(header.toByteArray())
+ val logcat =
+ ProcessBuilder("logcat", "-d", "-b", "main,crash", "-v", "threadtime")
+ .redirectErrorStream(true)
+ .start()
+ logcat.inputStream.use { it.copyTo(out) }
+ logcat.waitFor()
+}
diff --git a/app/src/main/java/app/passwordstore/ui/settings/SettingsScreen.kt b/app/src/main/java/app/passwordstore/ui/settings/SettingsScreen.kt
index a7bbe30a..2e7840ad 100644
--- a/app/src/main/java/app/passwordstore/ui/settings/SettingsScreen.kt
+++ b/app/src/main/java/app/passwordstore/ui/settings/SettingsScreen.kt
@@ -63,6 +63,7 @@ enum class SettingsAction {
ClearSecret,
DeleteRepository,
Export,
+ ExportLog,
}
/** Top bar with [title] and back, then [content] in one grouped surface, scrolling. */
@@ -324,6 +325,11 @@ fun SettingsSectionScreen(
onCheckedChange = { onBoolean(PreferenceKeys.ENABLE_DEBUG_LOGGING, it) },
summary = stringResource(R.string.pref_debug_logging_summary),
)
+ PreferenceAction(
+ title = stringResource(R.string.pref_export_log_title),
+ summary = stringResource(R.string.pref_export_log_summary),
+ onClick = { onAction(SettingsAction.ExportLog) },
+ )
}
SettingsSection.Pgp -> {
PreferenceAction(
diff --git a/app/src/main/java/app/passwordstore/ui/settings/SettingsViewModel.kt b/app/src/main/java/app/passwordstore/ui/settings/SettingsViewModel.kt
index cfc576ae..90aecb2a 100644
--- a/app/src/main/java/app/passwordstore/ui/settings/SettingsViewModel.kt
+++ b/app/src/main/java/app/passwordstore/ui/settings/SettingsViewModel.kt
@@ -8,6 +8,8 @@ package app.passwordstore.ui.settings
import android.app.Application
import android.content.SharedPreferences
import android.content.pm.ShortcutManager
+import android.net.Uri
+import android.os.Build
import androidx.annotation.StringRes
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
@@ -16,6 +18,7 @@ import androidx.core.content.edit
import androidx.core.content.getSystemService
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.viewModelScope
+import app.passwordstore.BuildConfig
import app.passwordstore.R
import app.passwordstore.data.crypto.PGPPassphraseCache
import app.passwordstore.data.repo.PasswordRepository
@@ -31,12 +34,16 @@ import app.passwordstore.util.settings.GitSettings
import app.passwordstore.util.settings.PasswordSortOrder
import app.passwordstore.util.settings.PreferenceKeys
import dagger.hilt.android.lifecycle.HiltViewModel
+import java.io.IOException
import java.nio.file.Files
import java.nio.file.LinkOption
import javax.inject.Inject
import kotlinx.coroutines.NonCancellable
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
+import logcat.LogPriority.ERROR
+import logcat.asLog
+import logcat.logcat
/** What the settings sections show: stored values, and the state rows depend on. */
data class SettingsState(
@@ -111,6 +118,27 @@ constructor(
state = read()
}
+ /** Saves the app's log to [uri]; false when that failed. */
+ suspend fun exportLog(uri: Uri): Boolean =
+ withContext(dispatcherProvider.io()) {
+ val header =
+ "HardenedPass ${BuildConfig.VERSION_NAME} (${BuildConfig.VERSION_CODE}), " +
+ "Android ${Build.VERSION.RELEASE} (SDK ${Build.VERSION.SDK_INT}), ${Build.MODEL}\n\n"
+ try {
+ val out =
+ getApplication<Application>().contentResolver.openOutputStream(uri)
+ ?: throw IOException("No stream for the chosen file")
+ out.use { writeAppLog(header, it) }
+ true
+ } catch (e: IOException) {
+ logcat(ERROR) { e.asLog() }
+ false
+ } catch (e: SecurityException) {
+ logcat(ERROR) { e.asLog() }
+ false
+ }
+ }
+
fun putBoolean(key: String, value: Boolean) {
prefs.edit { putBoolean(key, value) }
}
diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml
index b4569746..fed8adec 100644
--- a/app/src/main/res/values-it/strings.xml
+++ b/app/src/main/res/values-it/strings.xml
@@ -288,6 +288,10 @@
<string name="pref_rebase_on_pull_title">Rebase al pull</string>
<string name="pref_rebase_on_pull_summary">Durante pull o sincronizzazione, crea un merge commit con le modifiche del remote</string>
<string name="pref_rebase_on_pull_summary_on">Durante pull o sincronizzazione, esegui il rebase dei commit che non sono sul remote</string>
+ <string name="pref_export_log_title">Esporta log</string>
+ <string name="pref_export_log_summary">Salva in un file i log di questa app. Possono mostrare nomi delle voci, siti, app e il tuo server git: leggi il file prima di condividerlo</string>
+ <string name="log_exported">Log salvato</string>
+ <string name="log_export_failed">Impossibile salvare il log</string>
<string name="pref_push_after_commit_title">Push dopo ogni modifica</string>
<string name="pref_push_after_commit_summary">Esegui il push sul repository remoto dopo aver salvato, spostato o eliminato nell\'app</string>
<string name="git_push_after_commit_failed">Salvato sul dispositivo, ma push non riuscito. Sincronizza per riprovare</string>
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index fa9fb0f3..a415e95f 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -126,6 +126,10 @@
<string name="pref_rebase_on_pull_title">Rebase on pull</string>
<string name="pref_rebase_on_pull_summary">When pulling or syncing, create a merge commit with upstream changes</string>
<string name="pref_rebase_on_pull_summary_on">When pulling or syncing, rebase commits that are not present in the remote repository</string>
+ <string name="pref_export_log_title">Export log</string>
+ <string name="pref_export_log_summary">Save this app\'s logs to a file. They can show entry names, websites, apps and your git server, so read the file before sharing it</string>
+ <string name="log_exported">Log saved</string>
+ <string name="log_export_failed">Could not save the log</string>
<string name="pref_push_after_commit_title">Push after each change</string>
<string name="pref_push_after_commit_summary">Push to the remote repository after saving, moving or deleting in the app</string>
<string name="git_push_after_commit_failed">Saved on this device, but not pushed. Sync to try again</string>