Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions .github/workflows/decrypt-and-validate-data.sh
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
#!/bin/bash

if [ -n "$GPG_PASSPHRASE" ]; then
gpg --passphrase $GPG_PASSPHRASE --pinentry-mode loopback -o ./keys/debug.keystore -d ./keys/debug.keystore.gpg
gpg --passphrase $GPG_PASSPHRASE --pinentry-mode loopback -o ./keys/release.keystore -d ./keys/release.keystore.gpg
gpg --passphrase $GPG_PASSPHRASE --pinentry-mode loopback -o ./keys/google-cloud-key.json -d ./keys/google-cloud-key.json.gpg
gpg --passphrase $GPG_PASSPHRASE --pinentry-mode loopback -o ./ci.properties -d ./ci.properties.gpg
gpg --passphrase $GPG_PASSPHRASE --yes --pinentry-mode loopback -o ./keys/debug.keystore -d ./keys/debug.keystore.gpg
gpg --passphrase $GPG_PASSPHRASE --yes --pinentry-mode loopback -o ./keys/release.keystore -d ./keys/release.keystore.gpg
gpg --passphrase $GPG_PASSPHRASE --yes --pinentry-mode loopback -o ./keys/google-cloud-key.json -d ./keys/google-cloud-key.json.gpg
gpg --passphrase $GPG_PASSPHRASE --yes --pinentry-mode loopback -o ./ci.properties -d ./ci.properties.gpg

echo "3a15a7065ed4a62a747af2e3477b0a3e1940a7bc2946df638b902bcb186998e7 *keys/debug.keystore" | shasum --algorithm 256 --check
echo "36a3bb8b7bda141b414c2df7fac7dcd09a2775769c561e562d2b43f7b246bfa5 *keys/release.keystore" | shasum --algorithm 256 --check
echo "eac44fec5848bb6718b23ad433e73650352611953ae7f98c8e502c0491154da5 *keys/google-cloud-key.json" | shasum --algorithm 256 --check
echo "b009011968e80d5b99eaa181141e6c94178a538c3dac0e413c43d5f95f50f557 *ci.properties" | shasum --algorithm 256 --check
echo "43278a8837886a8e485f021e5bb4f0df14a057f796d0230cf2ea0e88709c98fa *ci.properties" | shasum --algorithm 256 --check
else
echo "Unable to decrypt secret data"
exit 1
Expand Down
10 changes: 3 additions & 7 deletions .github/workflows/pipeline.yml
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,6 @@ jobs:
strategy:
matrix:
include:
- command: assembleGplayDebug
fileName: app-gplay-debug.apk
filePath: ./app/build/outputs/apk/gplay/debug/app-gplay-debug.apk

- command: assembleGplayRelease
fileName: app-gplay-release.apk
filePath: ./app/build/outputs/apk/gplay/release/app-gplay-release.apk
Expand All @@ -72,9 +68,9 @@ jobs:
fileName: app-fdroid-release.apk
filePath: ./app/build/outputs/apk/fdroid/release/app-fdroid-release.apk

- command: assembleFdroidAutomation
fileName: app-fdroid-automation.apk
filePath: ./app/build/outputs/apk/fdroid/automation/app-fdroid-automation.apk
- command: assembleAutomationDebug
fileName: app-automation-debug.apk
filePath: ./app/build/outputs/apk/automation/debug/app-automation-debug.apk
steps:
- name: Checkout
uses: actions/checkout@v3
Expand Down
6 changes: 2 additions & 4 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,21 +26,19 @@ jobs:

- name: Build apk's
run: |
./gradlew app:assembleFdroidDebug app:assembleFdroidRelease app:assembleFdroidAutomation
app:assembleFdroidRelease app:assembleAutomationDebug

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Invoke Gradle in the release build step

On tag builds this step now asks the shell to execute a command literally named app:assembleFdroidRelease, so the GitHub release job will stop with command not found before any APKs are produced or renamed. This should still invoke Gradle, e.g. through ./gradlew, as the pipeline workflow does for these tasks.

Useful? React with 👍 / 👎.


- name: Rename files
run: |
cp ./app/build/outputs/apk/fdroid/debug/app-fdroid-debug.apk ./keepassvault-debug.apk
cp ./app/build/outputs/apk/fdroid/release/app-fdroid-release.apk ./keepassvault-release.apk
cp ./app/build/outputs/apk/fdroid/automation/app-fdroid-automation.apk ./keepassvault-test.apk
cp ./app/build/outputs/apk/automation/debug/app-automation-debug.apk ./keepassvault-test.apk

- name: Publish Github Release
uses: softprops/action-gh-release@v2
with:
generate_release_notes: true
prerelease: true
files: |
./keepassvault-debug.apk
./keepassvault-release.apk
./keepassvault-test.apk

Expand Down
4 changes: 2 additions & 2 deletions PRIVACY-POLICY.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ For a better experience, while using our Service, I may require you to provide u

**Log Data**

I want to inform you that whenever you use my Service, in a case of an error in the app I collect data and information (through third-party products) on your phone called Log Data. This Log Data may include information such as your device Internet Protocol (“IP”) address, device name, operating system version, the configuration of the app when utilizing my Service, the time and date of your use of the Service, and other statistics.
If you enable crash reporting in the application settings, then in a case of an error in the app I collect data and information (through third-party products) on your phone called Log Data. This Log Data may include information such as your device Internet Protocol (“IP”) address, device name, operating system version, the configuration of the app when utilizing my Service, the time and date of your use of the Service, and other statistics. Crash reporting is disabled by default.

**Cookies**

Expand Down Expand Up @@ -49,7 +49,7 @@ I do not knowingly collect personally identifiable information from children. I

I may update our Privacy Policy from time to time. Thus, you are advised to review this page periodically for any changes. I will notify you of any changes by posting the new Privacy Policy on this page.

This policy is effective as of 2022-10-22
This policy is effective as of 2026-07-06

**Contact Us**

Expand Down
23 changes: 17 additions & 6 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ val ciPropertiesFile = file("../ci.properties")

val propertyKeystorePassword = "KEYSTORE_PASSWORD"
val propertyKeystoreAlias = "KEYSTORE_ALIAS"
val propertySentryDsn = "SENTRY_DSN"

val debugKeyPath = "../keys/debug.keystore"
val releaseKeyPath = "../keys/release.keystore"
Expand All @@ -51,6 +52,10 @@ fun getCustomProperty(key: String): String {
return customProps.getProperty(key) ?: System.getenv(key).orEmpty()
}

fun String.toBuildConfigString(): String {
return "\"${replace("\\", "\\\\").replace("\"", "\\\"")}\""
}

val generateVersionPropertiesFile by tasks.registering {
description = "Generates version.properties for F-Droid."

Expand Down Expand Up @@ -91,6 +96,11 @@ android {
versionCode = formattedVersionCode.toInt()
versionName = formattedVersionName
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
buildConfigField(
"String",
"SENTRY_DSN",
getCustomProperty(propertySentryDsn).toBuildConfigString()
)

vectorDrawables {
useSupportLibrary = true
Expand Down Expand Up @@ -157,9 +167,15 @@ android {
productFlavors {
create("fdroid") {
dimension = "default"
buildConfigField("boolean", "IS_AUTOMATION_BUILD", "false")
}
create("automation") {
applicationIdSuffix = ".automation"
buildConfigField("boolean", "IS_AUTOMATION_BUILD", "true")
}
create("gplay") {
dimension = "default"
buildConfigField("boolean", "IS_AUTOMATION_BUILD", "false")
}
}

Expand All @@ -170,12 +186,6 @@ android {
versionNameSuffix = "d"
signingConfig = signingConfigs.getByName("debug")
}
create("automation") {
isDebuggable = true
isMinifyEnabled = false
signingConfig = signingConfigs.getByName("debug")
applicationIdSuffix = ".automation"
}
release {
isDebuggable = false
isMinifyEnabled = false
Expand Down Expand Up @@ -310,6 +320,7 @@ dependencies {
// Logging
implementation(libs.timber)
implementation(libs.treessence)
implementation(libs.sentry.android)

// KeePass
implementation(libs.kotpass)
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
package com.ivanovsky.passnotes.injection

import android.content.Context
import com.ivanovsky.passnotes.data.repository.settings.Settings
import com.ivanovsky.passnotes.domain.logger.LoggerInteractor
import com.ivanovsky.passnotes.BuildConfig
import com.ivanovsky.passnotes.injection.modules.CoreModule
import com.ivanovsky.passnotes.injection.modules.UiModule
import com.ivanovsky.passnotes.injection.modules.UseCaseModule
Expand All @@ -11,20 +9,18 @@ import com.ivanovsky.passnotes.injection.modules.debug.DebugFileSystemProvidersM
import com.ivanovsky.passnotes.injection.modules.debug.DebugModule
import org.koin.core.module.Module

// Is loaded via reflection in App.kt
class DebugModuleBuilder(
private val context: Context,
private val loggerInteractor: LoggerInteractor,
private val settings: Settings
private val startDeps: AppStartDependencies
) : DIModuleBuilder {

override var isExternalStorageAccessEnabled: Boolean = false

override fun buildModules(): List<Module> {
val isFakeFileSystemEnabled = settings.testToggles?.isFakeFileSystemEnabled ?: false
val isFakeFileSystemEnabled = startDeps.settings.testToggles?.isFakeFileSystemEnabled
?: BuildConfig.IS_AUTOMATION_BUILD

return listOf(
CoreModule.build(loggerInteractor),
CoreModule.build(startDeps),
DebugModule.build(),
DebugFileSystemProvidersModule.build(
isExternalStorageAccessEnabled = isExternalStorageAccessEnabled,
Expand Down
6 changes: 5 additions & 1 deletion app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@
android:theme="@style/AppTheme"
android:networkSecurityConfig="@xml/network_security_config">

<meta-data
android:name="io.sentry.auto-init"
android:value="false" />

<!-- Activities -->
<activity
android:name=".presentation.StartActivity"
Expand Down Expand Up @@ -79,4 +83,4 @@

</application>

</manifest>
</manifest>
39 changes: 22 additions & 17 deletions app/src/main/kotlin/com/ivanovsky/passnotes/App.kt
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
package com.ivanovsky.passnotes

import android.app.Application
import android.content.Context
import com.ivanovsky.passnotes.data.repository.settings.Settings
import com.ivanovsky.passnotes.data.repository.settings.SettingsImpl
import com.ivanovsky.passnotes.domain.logger.LoggerInteractor
import com.ivanovsky.passnotes.domain.loggingAndReporting.CrashReporterInteractor
import com.ivanovsky.passnotes.domain.loggingAndReporting.LoggerInteractor
import com.ivanovsky.passnotes.injection.AppStartDependencies
import com.ivanovsky.passnotes.injection.DIModuleBuilder
import com.ivanovsky.passnotes.injection.DebugModuleBuilder
import com.ivanovsky.passnotes.injection.DefaultModuleBuilder
import org.koin.android.ext.koin.androidContext
import org.koin.android.ext.koin.androidLogger
Expand All @@ -15,29 +16,33 @@ open class App : Application() {

open fun configureModuleBuilder(builder: DIModuleBuilder) {
// implementation should be flavor specific
if (BuildConfig.IS_AUTOMATION_BUILD) {
builder.isExternalStorageAccessEnabled = true
}
}

override fun onCreate() {
super.onCreate()

val settings = SettingsImpl(context = this)
val loggerInteractor = LoggerInteractor(context = this, settings)
.apply {
initialize()
}

val moduleBuilder = if (BuildConfig.DEBUG) {
val type = Class.forName("com.ivanovsky.passnotes.injection.DebugModuleBuilder")

val constructor = type.getConstructor(
Context::class.java,
LoggerInteractor::class.java,
Settings::class.java
)
val deps = AppStartDependencies(
context = this,
settings = settings,
loggerInteractor = LoggerInteractor(context = this, settings)
.apply {
initialize()
},
crashReporterInteractor = CrashReporterInteractor(context = this)
.apply {
initialize(settings)
}
)

constructor.newInstance(this, loggerInteractor, settings) as DIModuleBuilder
val moduleBuilder = if (BuildConfig.DEBUG) {
DebugModuleBuilder(deps)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Avoid referencing debug-only builder from main

Because app/src/main is compiled for release variants too, and the only DebugModuleBuilder implementation is under app/src/debug, assembleFdroidRelease and assembleGplayRelease will fail to resolve this reference even though it is guarded by BuildConfig.DEBUG; the Kotlin compiler still resolves both branches. Keep the reflection/source-set split or move a release-safe factory into main.

Useful? React with 👍 / 👎.

} else {
DefaultModuleBuilder(loggerInteractor)
DefaultModuleBuilder(deps)
}

configureModuleBuilder(moduleBuilder)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ interface Settings {
var isLockNotificationDialogEnabled: Boolean
var isLockDatabaseOnBack: Boolean
var isFileLogEnabled: Boolean
var isCrashReportingEnabled: Boolean
var searchOptions: SearchOptions
var isActivateSearchOnStart: Boolean
var sortType: SortType
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import com.ivanovsky.passnotes.data.repository.settings.SettingsImpl.Pref.GIT_US
import com.ivanovsky.passnotes.data.repository.settings.SettingsImpl.Pref.GIT_USER_NAME
import com.ivanovsky.passnotes.data.repository.settings.SettingsImpl.Pref.IS_ACTIVATE_SEARCH_ON_START
import com.ivanovsky.passnotes.data.repository.settings.SettingsImpl.Pref.IS_BIOMETRIC_UNLOCK_ENABLED
import com.ivanovsky.passnotes.data.repository.settings.SettingsImpl.Pref.IS_CRASH_REPORTING_ENABLED
import com.ivanovsky.passnotes.data.repository.settings.SettingsImpl.Pref.IS_EXTERNAL_STORAGE_CACHE_ENABLED
import com.ivanovsky.passnotes.data.repository.settings.SettingsImpl.Pref.IS_FILE_LOG_ENABLED
import com.ivanovsky.passnotes.data.repository.settings.SettingsImpl.Pref.IS_GROUPS_AT_START_ENABLED
Expand Down Expand Up @@ -101,6 +102,12 @@ class SettingsImpl(private val context: Context) : Settings {
putBoolean(IS_FILE_LOG_ENABLED, value)
}

override var isCrashReportingEnabled: Boolean
get() = getBoolean(IS_CRASH_REPORTING_ENABLED)
set(value) {
putBoolean(IS_CRASH_REPORTING_ENABLED, value)
}

override var isBiometricUnlockEnabled: Boolean
get() = getBoolean(IS_BIOMETRIC_UNLOCK_ENABLED)
set(value) {
Expand Down Expand Up @@ -318,6 +325,11 @@ class SettingsImpl(private val context: Context) : Settings {
type = BOOLEAN,
defaultValue = false
),
IS_CRASH_REPORTING_ENABLED(
keyId = R.string.pref_is_crash_reporting_enabled,
type = BOOLEAN,
defaultValue = false
),
IS_POSTPONED_SYNC_ENABLED(
keyId = R.string.pref_is_postponed_sync_enabled,
type = BOOLEAN,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ import com.ivanovsky.passnotes.data.entity.OperationError.newGenericIOError
import com.ivanovsky.passnotes.data.entity.OperationResult
import com.ivanovsky.passnotes.domain.DispatcherProvider
import com.ivanovsky.passnotes.domain.entity.exception.Stacktrace
import com.ivanovsky.passnotes.domain.logger.LoggerInteractor
import com.ivanovsky.passnotes.domain.loggingAndReporting.CrashReporterInteractor
import com.ivanovsky.passnotes.domain.loggingAndReporting.LoggerInteractor
import com.ivanovsky.passnotes.domain.usecases.LockDatabaseUseCase
import com.ivanovsky.passnotes.domain.usecases.RemoveBiometricDataUseCase
import java.io.File
Expand All @@ -16,13 +17,21 @@ class AppSettingsInteractor(
private val loggerInteractor: LoggerInteractor,
private val dispatchers: DispatcherProvider,
private val lockUseCase: LockDatabaseUseCase,
private val removeBiometricDataUseCase: RemoveBiometricDataUseCase
private val removeBiometricDataUseCase: RemoveBiometricDataUseCase,
private val crashReporterInteractor: CrashReporterInteractor
) {

fun isCrashReportingAvailable(): Boolean =
crashReporterInteractor.isAvailable

fun reInitializeLogging() {
loggerInteractor.initialize()
}

fun setCrashReportingEnabled(isEnabled: Boolean) {
crashReporterInteractor.setEnabled(isEnabled)
}

fun lockDatabase() {
lockUseCase.lockIfNeed()
}
Expand Down
Loading
Loading