Skip to content

Commit 1e43eb7

Browse files
committed
Remove requery BlockingEntityStore
PretixScan.data is no longer needed. This change removes the setup of the BlockingEntityStore instance and moves the SQLCipher migration logic to the init code for the SQLDelight database.
1 parent 807e44e commit 1e43eb7

File tree

4 files changed

+91
-141
lines changed

4 files changed

+91
-141
lines changed

pretixscan/app/src/main/java/eu/pretix/pretixscan/droid/AndroidDatabaseSource.kt

Lines changed: 0 additions & 24 deletions
This file was deleted.

pretixscan/app/src/main/java/eu/pretix/pretixscan/droid/AndroidSqlCipherDatabaseSource.kt

Lines changed: 0 additions & 24 deletions
This file was deleted.

pretixscan/app/src/main/java/eu/pretix/pretixscan/droid/PretixScan.kt

Lines changed: 61 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -4,146 +4,114 @@ import android.database.sqlite.SQLiteException
44
import android.os.Build
55
import androidx.appcompat.app.AppCompatDelegate
66
import androidx.multidex.MultiDexApplication
7-
import androidx.sqlite.db.SupportSQLiteDatabase
7+
import app.cash.sqldelight.db.QueryResult
88
import app.cash.sqldelight.driver.android.AndroidSqliteDriver
99
import com.facebook.flipper.android.AndroidFlipperClient
1010
import com.facebook.flipper.core.FlipperClient
1111
import com.facebook.soloader.SoLoader
12-
import eu.pretix.libpretixsync.Models
1312
import eu.pretix.libpretixsync.check.AsyncCheckProvider
1413
import eu.pretix.libpretixsync.check.OnlineCheckProvider
1514
import eu.pretix.libpretixsync.check.ProxyCheckProvider
1615
import eu.pretix.libpretixsync.check.TicketCheckProvider
17-
import eu.pretix.libpretixsync.db.Migrations
1816
import eu.pretix.libpretixsync.sqldelight.AndroidUtilDateAdapter
1917
import eu.pretix.libpretixsync.sqldelight.BigDecimalAdapter
2018
import eu.pretix.pretixscan.droid.connectivity.ConnectivityHelper
2119
import eu.pretix.pretixscan.sqldelight.SyncDatabase
2220
import eu.pretix.pretixscan.utils.KeystoreHelper
21+
import eu.pretix.pretixscan.utils.createDriver
2322
import eu.pretix.pretixscan.utils.createSyncDatabase
2423
import eu.pretix.pretixscan.utils.readVersionPragma
25-
import io.requery.BlockingEntityStore
26-
import io.requery.Persistable
27-
import io.requery.sql.EntityDataStore
2824
import net.zetetic.database.sqlcipher.SQLiteConnection
2925
import net.zetetic.database.sqlcipher.SQLiteDatabase
3026
import net.zetetic.database.sqlcipher.SQLiteDatabaseHook
31-
import net.zetetic.database.sqlcipher.SupportOpenHelperFactory
3227
import java.util.concurrent.locks.ReentrantLock
3328

3429

3530
class PretixScan : MultiDexApplication() {
36-
private var dataStore: BlockingEntityStore<Persistable>? = null
3731
val fileStorage = AndroidFileStorage(this)
3832
val syncLock = ReentrantLock()
3933
var flipperInit: FlipperInitializer.IntializationResult? = null
4034
lateinit var connectivityHelper: ConnectivityHelper
4135

42-
private fun migrateSqlCipher(name: String, dbPass: String) {
36+
private fun migrateSqlCipher(name: String, dbPass: String, driver: AndroidSqliteDriver): Boolean {
4337
System.loadLibrary("sqlcipher")
4438

45-
val databaseFile = getDatabasePath(name)
46-
SQLiteDatabase.openOrCreateDatabase(databaseFile, dbPass, null, null, object: SQLiteDatabaseHook {
47-
override fun preKey(connection: SQLiteConnection) {
48-
}
49-
50-
override fun postKey(connection: SQLiteConnection) {
51-
val result = connection.executeForLong("PRAGMA cipher_migrate;", emptyArray(), null)
52-
if (result != 0L) {
53-
throw SQLiteException("cipher_migrate failed")
54-
}
55-
}
56-
}).close()
57-
}
39+
try {
40+
driver.executeQuery(
41+
identifier = null,
42+
sql = "select count(*) from sqlite_master;",
43+
mapper = { cursor ->
44+
cursor.next()
45+
QueryResult.Value(cursor.getLong(0))
46+
},
47+
parameters = 0,
48+
)
49+
return true
50+
} catch (e: SQLiteException) {
51+
try {
52+
val databaseFile = getDatabasePath(name)
53+
SQLiteDatabase.openOrCreateDatabase(
54+
databaseFile,
55+
dbPass,
56+
null,
57+
null,
58+
object : SQLiteDatabaseHook {
59+
override fun preKey(connection: SQLiteConnection) {
60+
}
5861

59-
val data: BlockingEntityStore<Persistable>
60-
get() {
61-
if (dataStore == null) {
62-
if (BuildConfig.DEBUG) {
63-
// Do not encrypt on debug, because it breaks Stetho
64-
val source = AndroidDatabaseSource(this, Models.DEFAULT, Migrations.CURRENT_VERSION)
65-
source.setLoggingEnabled(BuildConfig.DEBUG)
66-
val configuration = source.configuration
67-
dataStore = EntityDataStore(configuration)
68-
} else {
69-
val dbPass = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) KeystoreHelper.secureValue(KEYSTORE_PASSWORD, true)
70-
else KEYSTORE_PASSWORD
71-
72-
var source = AndroidSqlCipherDatabaseSource(
73-
this,
74-
Models.DEFAULT,
75-
Models.DEFAULT.name,
76-
dbPass,
77-
Migrations.CURRENT_VERSION
78-
)
79-
try {
80-
// check if database has been decrypted
81-
source.readableDatabase.rawQuery("select count(*) from sqlite_master;", emptyArray())
82-
} catch (e: SQLiteException) {
83-
try {
84-
source.close()
85-
migrateSqlCipher(Models.DEFAULT.name, dbPass)
86-
source = AndroidSqlCipherDatabaseSource(
87-
this,
88-
Models.DEFAULT,
89-
Models.DEFAULT.name,
90-
dbPass,
91-
Migrations.CURRENT_VERSION
92-
)
93-
source.readableDatabase.rawQuery("select count(*) from sqlite_master;", emptyArray())
94-
} catch (e: SQLiteException) {
95-
// still not decrypted? then we probably lost the key due to a keystore issue
96-
// let's start fresh, there's no reasonable other way to let the user out of this
97-
this.deleteDatabase(Models.DEFAULT.getName())
98-
source = AndroidSqlCipherDatabaseSource(
99-
this,
100-
Models.DEFAULT,
101-
Models.DEFAULT.name,
102-
dbPass,
103-
Migrations.CURRENT_VERSION
62+
override fun postKey(connection: SQLiteConnection) {
63+
val result = connection.executeForLong(
64+
"PRAGMA cipher_migrate;",
65+
emptyArray(),
66+
null
10467
)
68+
if (result != 0L) {
69+
throw SQLiteException("cipher_migrate failed")
70+
}
10571
}
106-
}
107-
source.setLoggingEnabled(false)
108-
109-
val configuration = source.configuration
110-
dataStore = EntityDataStore(configuration)
111-
}
72+
}).close()
73+
return true
74+
} catch (e: SQLiteException) {
75+
// still not decrypted? then we probably lost the key due to a keystore issue
76+
// let's start fresh, there's no reasonable other way to let the user out of this
77+
this.deleteDatabase(name)
78+
return false
11279
}
113-
return dataStore!!
11480
}
81+
}
11582

11683
val db: SyncDatabase by lazy {
117-
// Access data to init schema through requery if it hasn't been created already
118-
data.raw("PRAGMA user_version;").first()
84+
val dbName = "default"
11985

12086
val dbPass = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) KeystoreHelper.secureValue(KEYSTORE_PASSWORD, true)
12187
else KEYSTORE_PASSWORD
12288

12389
val androidDriver = if (BuildConfig.DEBUG) {
124-
AndroidSqliteDriver(
125-
schema = SyncDatabase.Schema,
90+
createDriver(
12691
context = this.applicationContext,
127-
name = "default",
128-
callback = object : AndroidSqliteDriver.Callback(SyncDatabase.Schema) {
129-
override fun onOpen(db: SupportSQLiteDatabase) {
130-
db.setForeignKeyConstraintsEnabled(true)
131-
}
132-
},
92+
dbName = dbName,
93+
dbPass = null,
13394
)
13495
} else {
13596
System.loadLibrary("sqlcipher")
136-
AndroidSqliteDriver(
137-
schema = SyncDatabase.Schema,
97+
val driver = createDriver(
13898
context = this.applicationContext,
139-
name = "default",
140-
callback = object : AndroidSqliteDriver.Callback(SyncDatabase.Schema) {
141-
override fun onOpen(db: SupportSQLiteDatabase) {
142-
db.setForeignKeyConstraintsEnabled(true)
143-
}
144-
},
145-
factory = SupportOpenHelperFactory(dbPass.toByteArray())
99+
dbName = dbName,
100+
dbPass = dbPass,
146101
)
102+
103+
val migrationSuccess = migrateSqlCipher(dbName, dbPass, driver)
104+
if (migrationSuccess) {
105+
driver
106+
} else {
107+
// Re-open database if we had to delete it during migration
108+
driver.close()
109+
createDriver(
110+
context = this.applicationContext,
111+
dbName = dbName,
112+
dbPass = dbPass,
113+
)
114+
}
147115
}
148116

149117
// Uncomment LogSqliteDriver for verbose logging

pretixscan/app/src/main/java/eu/pretix/pretixscan/utils/SqlDelightUtils.kt

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
package eu.pretix.pretixscan.utils
22

3+
import android.content.Context
4+
import androidx.sqlite.db.SupportSQLiteDatabase
35
import app.cash.sqldelight.ColumnAdapter
46
import app.cash.sqldelight.TransacterImpl
57
import app.cash.sqldelight.db.QueryResult
68
import app.cash.sqldelight.db.SqlDriver
9+
import app.cash.sqldelight.driver.android.AndroidSqliteDriver
710
import eu.pretix.libpretixsync.sqldelight.CheckIn
811
import eu.pretix.libpretixsync.sqldelight.Closing
912
import eu.pretix.libpretixsync.sqldelight.Event
@@ -13,6 +16,7 @@ import eu.pretix.libpretixsync.sqldelight.ReceiptLine
1316
import eu.pretix.libpretixsync.sqldelight.ReceiptPayment
1417
import eu.pretix.libpretixsync.sqldelight.SubEvent
1518
import eu.pretix.pretixscan.sqldelight.SyncDatabase
19+
import net.zetetic.database.sqlcipher.SupportOpenHelperFactory
1620
import java.math.BigDecimal
1721
import java.util.Date
1822

@@ -95,3 +99,29 @@ fun readVersionPragma(driver: SqlDriver): Long? {
9599
parameters = 0,
96100
).value
97101
}
102+
103+
fun createDriver(context: Context, dbName: String, dbPass: String?) =
104+
if (dbPass != null) {
105+
AndroidSqliteDriver(
106+
schema = SyncDatabase.Schema,
107+
context = context,
108+
name = dbName,
109+
callback = object : AndroidSqliteDriver.Callback(SyncDatabase.Schema) {
110+
override fun onOpen(db: SupportSQLiteDatabase) {
111+
db.setForeignKeyConstraintsEnabled(true)
112+
}
113+
},
114+
factory = SupportOpenHelperFactory(dbPass.toByteArray())
115+
)
116+
} else {
117+
AndroidSqliteDriver(
118+
schema = SyncDatabase.Schema,
119+
context = context,
120+
name = dbName,
121+
callback = object : AndroidSqliteDriver.Callback(SyncDatabase.Schema) {
122+
override fun onOpen(db: SupportSQLiteDatabase) {
123+
db.setForeignKeyConstraintsEnabled(true)
124+
}
125+
},
126+
)
127+
}

0 commit comments

Comments
 (0)