Merge sql crypto store implementation
This commit is contained in:
commit
9a4cad1e45
1
.gitignore
vendored
1
.gitignore
vendored
@ -14,3 +14,4 @@
|
||||
/tmp
|
||||
|
||||
ktlint
|
||||
.idea
|
||||
|
19
CHANGES.md
19
CHANGES.md
@ -2,52 +2,40 @@ Changes in RiotX 0.19.0 (2020-XX-XX)
|
||||
===================================================
|
||||
|
||||
Features ✨:
|
||||
- Change password (#528)
|
||||
- Cross-Signing | Support SSSS secret sharing (#944)
|
||||
- Cross-Signing | Verify new session from existing session (#1134)
|
||||
- Cross-Signing | Bootstraping cross signing with 4S from mobile (#985)
|
||||
- Save media files to Gallery (#973)
|
||||
|
||||
|
||||
Improvements 🙌:
|
||||
- Verification DM / Handle concurrent .start after .ready (#794)
|
||||
- Reimplementation of multiple attachment picker
|
||||
- Cross-Signing | Update Shield Logic for DM (#963)
|
||||
- Cross-Signing | Complete security new session design update (#1135)
|
||||
- Cross-Signing | Setup key backup as part of SSSS bootstrapping (#1201)
|
||||
- Cross-Signing | Gossip key backup recovery key (#1200)
|
||||
- Show room encryption status as a bubble tile (#1078)
|
||||
- UX/UI | Add indicator to home tab on invite (#957)
|
||||
- Cross-Signing | Restore history after recover from passphrase (#1214)
|
||||
- Cross-Sign | QR code scan confirmation screens design update (#1187)
|
||||
- Emoji Verification | It's not the same butterfly! (#1220)
|
||||
- Cross-Signing | Composer decoration: shields (#1077)
|
||||
- Cross-Signing | Migrate existing keybackup to cross signing with 4S from mobile (#1197)
|
||||
|
||||
Bugfix 🐛:
|
||||
- Fix summary notification staying after "mark as read"
|
||||
- Missing avatar/displayname after verification request message (#841)
|
||||
- Crypto | RiotX sometimes rotate the current device keys (#1170)
|
||||
- RiotX can't restore cross signing keys saved by web in SSSS (#1174)
|
||||
- Cross- Signing | After signin in new session, verification paper trail in DM is off (#1191)
|
||||
- Failed to encrypt message in room (message stays in red), [thanks to pwr22] (#925)
|
||||
- Cross-Signing | web <-> riotX After QR code scan, gossiping fails (#1210)
|
||||
- Fix crash when trying to download file without internet connection (#1229)
|
||||
- Local echo are not updated in timeline (for failed & encrypted states)
|
||||
- Render image event even if thumbnail_info does not have mimetype defined (#1209)
|
||||
- RiotX now uses as many threads as it needs to do work and send messages (#1221)
|
||||
- Fix issue with media path (#1227)
|
||||
|
||||
Translations 🗣:
|
||||
-
|
||||
|
||||
SDK API changes ⚠️:
|
||||
- Increase targetSdkVersion to 29
|
||||
- Implementation of SqlCryptoStore on top of SQLDelight
|
||||
|
||||
Build 🧱:
|
||||
- Compile with Android SDK 29 (Android Q)
|
||||
-
|
||||
|
||||
Other changes:
|
||||
- Add a setting to prevent screenshots of the application, disabled by default (#1027)
|
||||
- Increase File Logger capacities ( + use dev log preferences)
|
||||
|
||||
Changes in RiotX 0.18.1 (2020-03-17)
|
||||
@ -456,7 +444,6 @@ Bugfix:
|
||||
- Fix messages with empty `in_reply_to` not rendering (#447)
|
||||
- Fix clear cache (#408) and Logout (#205)
|
||||
- Fix `(edited)` link can be copied to clipboard (#402)
|
||||
- KeyBackup / SSSS | Should get the key from SSSS instead of asking recovery Key (#1163)
|
||||
|
||||
Build:
|
||||
- Split APK: generate one APK per arch, to reduce APK size of about 30%
|
||||
|
@ -71,6 +71,10 @@ android {
|
||||
kotlinOptions {
|
||||
jvmTarget = "1.8"
|
||||
}
|
||||
|
||||
packagingOptions {
|
||||
pickFirst 'META-INF/kotlinx-coroutines-core.kotlin_module'
|
||||
}
|
||||
}
|
||||
|
||||
static def gitRevision() {
|
||||
|
@ -18,14 +18,18 @@ package im.vector.matrix.android.internal.crypto.verification.qrcode
|
||||
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import im.vector.matrix.android.InstrumentedTest
|
||||
import im.vector.matrix.android.api.session.crypto.verification.PendingVerificationRequest
|
||||
import im.vector.matrix.android.api.session.crypto.verification.VerificationMethod
|
||||
import im.vector.matrix.android.api.session.crypto.verification.VerificationService
|
||||
import im.vector.matrix.android.api.session.room.timeline.Timeline
|
||||
import im.vector.matrix.android.api.session.room.timeline.TimelineEvent
|
||||
import im.vector.matrix.android.api.session.room.timeline.TimelineSettings
|
||||
import im.vector.matrix.android.common.CommonTestHelper
|
||||
import im.vector.matrix.android.common.CryptoTestHelper
|
||||
import im.vector.matrix.android.common.TestConstants
|
||||
import im.vector.matrix.android.internal.crypto.model.rest.UserPasswordAuth
|
||||
import im.vector.matrix.android.api.session.crypto.verification.PendingVerificationRequest
|
||||
import org.amshove.kluent.shouldBe
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.FixMethodOrder
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
@ -229,4 +233,46 @@ class VerificationTest : InstrumentedTest {
|
||||
|
||||
cryptoTestData.cleanUp(mTestHelper)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun test_alice_sends_text_message_and_bob_can_decrypt() {
|
||||
val lock = CountDownLatch(1)
|
||||
|
||||
val cryptoTestData = mCryptoTestHelper.doE2ETestWithAliceAndBobInARoom()
|
||||
|
||||
val aliceSession = cryptoTestData.firstSession
|
||||
val bobSession = cryptoTestData.secondSession!!
|
||||
|
||||
val roomFromBobPOV = bobSession.getRoom(cryptoTestData.roomId)!!
|
||||
|
||||
aliceSession.getRoom(cryptoTestData.roomId)!!.sendTextMessage("test")
|
||||
|
||||
val bobEventsListener = object : Timeline.Listener {
|
||||
override fun onTimelineFailure(throwable: Throwable) {
|
||||
// noop
|
||||
}
|
||||
|
||||
override fun onNewTimelineEvents(eventIds: List<String>) {
|
||||
// noop
|
||||
}
|
||||
|
||||
override fun onTimelineUpdated(snapshot: List<TimelineEvent>) {
|
||||
if (snapshot.isNotEmpty() && snapshot.first().root.isEncrypted()) {
|
||||
lock.countDown()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val bobTimeline = roomFromBobPOV.createTimeline(null, TimelineSettings(20))
|
||||
bobTimeline.start()
|
||||
bobTimeline.addListener(bobEventsListener)
|
||||
|
||||
mTestHelper.await(lock)
|
||||
|
||||
bobTimeline.getTimelineEventAtIndex(0)?.root?.let {
|
||||
val decryptionResult = bobSession.cryptoService().decryptEvent(it, "")
|
||||
val text = (decryptionResult.clearEvent["content"] as Map<*, *>)["body"]
|
||||
assertEquals("test", text)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -16,9 +16,15 @@
|
||||
|
||||
package im.vector.matrix.android.internal.crypto
|
||||
|
||||
import android.content.Context
|
||||
import android.util.Log
|
||||
import com.squareup.sqldelight.ColumnAdapter
|
||||
import com.squareup.sqldelight.android.AndroidSqliteDriver
|
||||
import com.squareup.sqldelight.logs.LogSqliteDriver
|
||||
import dagger.Binds
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import im.vector.matrix.android.BuildConfig
|
||||
import im.vector.matrix.android.api.session.crypto.CryptoService
|
||||
import im.vector.matrix.android.api.session.crypto.crosssigning.CrossSigningService
|
||||
import im.vector.matrix.android.internal.crypto.api.CryptoApi
|
||||
@ -55,9 +61,9 @@ import im.vector.matrix.android.internal.crypto.keysbackup.tasks.StoreRoomSessio
|
||||
import im.vector.matrix.android.internal.crypto.keysbackup.tasks.StoreSessionsDataTask
|
||||
import im.vector.matrix.android.internal.crypto.keysbackup.tasks.UpdateKeysBackupVersionTask
|
||||
import im.vector.matrix.android.internal.crypto.store.IMXCryptoStore
|
||||
import im.vector.matrix.android.internal.crypto.store.db.RealmCryptoStore
|
||||
import im.vector.matrix.android.internal.crypto.store.db.RealmCryptoStoreMigration
|
||||
import im.vector.matrix.android.internal.crypto.store.db.RealmCryptoStoreModule
|
||||
import im.vector.matrix.android.internal.crypto.store.db.SqlCryptoStore
|
||||
import im.vector.matrix.android.internal.crypto.tasks.ClaimOneTimeKeysForUsersDeviceTask
|
||||
import im.vector.matrix.android.internal.crypto.tasks.DefaultClaimOneTimeKeysForUsersDevice
|
||||
import im.vector.matrix.android.internal.crypto.tasks.DefaultDeleteDeviceTask
|
||||
@ -87,12 +93,13 @@ import im.vector.matrix.android.internal.crypto.tasks.UploadKeysTask
|
||||
import im.vector.matrix.android.internal.crypto.tasks.UploadSignaturesTask
|
||||
import im.vector.matrix.android.internal.crypto.tasks.UploadSigningKeysTask
|
||||
import im.vector.matrix.android.internal.database.RealmKeysUtils
|
||||
import im.vector.matrix.android.internal.di.CryptoDatabase
|
||||
import im.vector.matrix.android.internal.di.SessionFilesDirectory
|
||||
import im.vector.matrix.android.internal.di.UserMd5
|
||||
import im.vector.matrix.android.internal.session.SessionScope
|
||||
import im.vector.matrix.android.internal.session.cache.ClearCacheTask
|
||||
import im.vector.matrix.android.internal.session.cache.RealmClearCacheTask
|
||||
import im.vector.matrix.sqldelight.crypto.CrossSigningInfoEntity
|
||||
import im.vector.matrix.sqldelight.crypto.CryptoDatabase
|
||||
import io.realm.RealmConfiguration
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.SupervisorJob
|
||||
@ -108,7 +115,7 @@ internal abstract class CryptoModule {
|
||||
|
||||
@JvmStatic
|
||||
@Provides
|
||||
@CryptoDatabase
|
||||
@im.vector.matrix.android.internal.di.CryptoDatabase
|
||||
@SessionScope
|
||||
fun providesRealmConfiguration(@SessionFilesDirectory directory: File,
|
||||
@UserMd5 userMd5: String,
|
||||
@ -125,6 +132,31 @@ internal abstract class CryptoModule {
|
||||
.build()
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
@Provides
|
||||
@SessionScope
|
||||
fun providesCryptoDatabase(context: Context, @SessionFilesDirectory directory: File): CryptoDatabase {
|
||||
val name = "${directory.name}-matrix-sdk-crypto.db"
|
||||
val driver = if (BuildConfig.DEBUG) {
|
||||
LogSqliteDriver(AndroidSqliteDriver(CryptoDatabase.Schema, context, name)) { log ->
|
||||
Log.d("SQLite", log)
|
||||
}
|
||||
} else {
|
||||
AndroidSqliteDriver(CryptoDatabase.Schema, context, name)
|
||||
}
|
||||
|
||||
val listOfStringAdapter = object : ColumnAdapter<List<String>, String> {
|
||||
override fun decode(databaseValue: String) = databaseValue.split(",")
|
||||
override fun encode(value: List<String>) = value.joinToString(separator = ",")
|
||||
}
|
||||
return CryptoDatabase(
|
||||
driver = driver,
|
||||
crossSigningInfoEntityAdapter = CrossSigningInfoEntity.Adapter(
|
||||
usagesAdapter = listOfStringAdapter
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
@Provides
|
||||
@SessionScope
|
||||
@ -134,8 +166,8 @@ internal abstract class CryptoModule {
|
||||
|
||||
@JvmStatic
|
||||
@Provides
|
||||
@CryptoDatabase
|
||||
fun providesClearCacheTask(@CryptoDatabase
|
||||
@im.vector.matrix.android.internal.di.CryptoDatabase
|
||||
fun providesClearCacheTask(@im.vector.matrix.android.internal.di.CryptoDatabase
|
||||
realmConfiguration: RealmConfiguration): ClearCacheTask {
|
||||
return RealmClearCacheTask(realmConfiguration)
|
||||
}
|
||||
@ -243,7 +275,7 @@ internal abstract class CryptoModule {
|
||||
abstract fun bindCrossSigningService(service: DefaultCrossSigningService): CrossSigningService
|
||||
|
||||
@Binds
|
||||
abstract fun bindCryptoStore(store: RealmCryptoStore): IMXCryptoStore
|
||||
abstract fun bindCryptoStore(store: SqlCryptoStore): IMXCryptoStore
|
||||
|
||||
@Binds
|
||||
abstract fun bindComputeShieldTrustTask(task: DefaultComputeTrustTask): ComputeTrustTask
|
||||
|
@ -69,7 +69,6 @@ import im.vector.matrix.android.internal.crypto.model.ImportRoomKeysResult
|
||||
import im.vector.matrix.android.internal.crypto.model.OlmInboundGroupSessionWrapper
|
||||
import im.vector.matrix.android.internal.crypto.store.IMXCryptoStore
|
||||
import im.vector.matrix.android.internal.crypto.store.SavedKeyBackupKeyInfo
|
||||
import im.vector.matrix.android.internal.crypto.store.db.model.KeysBackupDataEntity
|
||||
import im.vector.matrix.android.internal.di.MoshiProvider
|
||||
import im.vector.matrix.android.internal.di.UserId
|
||||
import im.vector.matrix.android.internal.extensions.foldToCallback
|
||||
@ -1154,11 +1153,11 @@ internal class DefaultKeysBackupService @Inject constructor(
|
||||
* Update the DB with data fetch from the server
|
||||
*/
|
||||
private fun onServerDataRetrieved(count: Int?, hash: String?) {
|
||||
cryptoStore.setKeysBackupData(KeysBackupDataEntity()
|
||||
.apply {
|
||||
backupLastServerNumberOfKeys = count
|
||||
backupLastServerHash = hash
|
||||
}
|
||||
cryptoStore.setKeysBackupData(
|
||||
im.vector.matrix.android.internal.crypto.model.rest.KeysBackupData(
|
||||
backupLastServerNumberOfKeys = count,
|
||||
backupLastServerHash = hash
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright (c) 2020 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package im.vector.matrix.android.internal.crypto.model.rest
|
||||
|
||||
internal data class KeysBackupData(val backupLastServerHash: String?, val backupLastServerNumberOfKeys: Int?)
|
@ -32,8 +32,8 @@ import im.vector.matrix.android.internal.crypto.model.CryptoCrossSigningKey
|
||||
import im.vector.matrix.android.internal.crypto.model.CryptoDeviceInfo
|
||||
import im.vector.matrix.android.internal.crypto.model.OlmInboundGroupSessionWrapper
|
||||
import im.vector.matrix.android.internal.crypto.model.OlmSessionWrapper
|
||||
import im.vector.matrix.android.internal.crypto.model.rest.KeysBackupData
|
||||
import im.vector.matrix.android.internal.crypto.model.rest.RoomKeyRequestBody
|
||||
import im.vector.matrix.android.internal.crypto.store.db.model.KeysBackupDataEntity
|
||||
import org.matrix.olm.OlmAccount
|
||||
|
||||
/**
|
||||
@ -104,14 +104,14 @@ internal interface IMXCryptoStore {
|
||||
/**
|
||||
* Get the current keys backup local data
|
||||
*/
|
||||
fun getKeysBackupData(): KeysBackupDataEntity?
|
||||
fun getKeysBackupData(): KeysBackupData?
|
||||
|
||||
/**
|
||||
* Set the keys backup local data
|
||||
*
|
||||
* @param keysBackupData the keys backup local data, or null to erase data
|
||||
*/
|
||||
fun setKeysBackupData(keysBackupData: KeysBackupDataEntity?)
|
||||
fun setKeysBackupData(keysBackupData: KeysBackupData?)
|
||||
|
||||
/**
|
||||
* @return the devices statuses map (userId -> tracking status)
|
||||
|
@ -41,6 +41,7 @@ import im.vector.matrix.android.internal.crypto.model.CryptoCrossSigningKey
|
||||
import im.vector.matrix.android.internal.crypto.model.CryptoDeviceInfo
|
||||
import im.vector.matrix.android.internal.crypto.model.OlmInboundGroupSessionWrapper
|
||||
import im.vector.matrix.android.internal.crypto.model.OlmSessionWrapper
|
||||
import im.vector.matrix.android.internal.crypto.model.rest.KeysBackupData
|
||||
import im.vector.matrix.android.internal.crypto.model.rest.RoomKeyRequestBody
|
||||
import im.vector.matrix.android.internal.crypto.model.toEntity
|
||||
import im.vector.matrix.android.internal.crypto.store.IMXCryptoStore
|
||||
@ -705,13 +706,18 @@ internal class RealmCryptoStore @Inject constructor(
|
||||
}
|
||||
}
|
||||
|
||||
override fun getKeysBackupData(): KeysBackupDataEntity? {
|
||||
override fun getKeysBackupData(): KeysBackupData? {
|
||||
return doRealmQueryAndCopy(realmConfiguration) {
|
||||
it.where<KeysBackupDataEntity>().findFirst()
|
||||
}?.let { entity ->
|
||||
return KeysBackupData(
|
||||
backupLastServerHash = entity.backupLastServerHash,
|
||||
backupLastServerNumberOfKeys = entity.backupLastServerNumberOfKeys
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override fun setKeysBackupData(keysBackupData: KeysBackupDataEntity?) {
|
||||
override fun setKeysBackupData(keysBackupData: KeysBackupData?) {
|
||||
doRealmTransaction(realmConfiguration) {
|
||||
if (keysBackupData == null) {
|
||||
// Clear the table
|
||||
@ -720,7 +726,10 @@ internal class RealmCryptoStore @Inject constructor(
|
||||
.deleteAllFromRealm()
|
||||
} else {
|
||||
// Only one object
|
||||
it.copyToRealmOrUpdate(keysBackupData)
|
||||
it.copyToRealmOrUpdate(it.createObject(KeysBackupDataEntity::class.java).apply {
|
||||
backupLastServerHash = keysBackupData.backupLastServerHash
|
||||
backupLastServerNumberOfKeys = keysBackupData.backupLastServerNumberOfKeys
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,242 @@
|
||||
/*
|
||||
* Copyright (c) 2020 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package im.vector.matrix.android.internal.crypto.store.db
|
||||
|
||||
import com.squareup.moshi.JsonAdapter
|
||||
import com.squareup.moshi.Moshi
|
||||
import com.squareup.moshi.Types
|
||||
import im.vector.matrix.android.api.extensions.tryThis
|
||||
import im.vector.matrix.android.api.util.JsonDict
|
||||
import im.vector.matrix.android.internal.crypto.GossipRequestType
|
||||
import im.vector.matrix.android.internal.crypto.GossipingRequestState
|
||||
import im.vector.matrix.android.internal.crypto.IncomingRoomKeyRequest
|
||||
import im.vector.matrix.android.internal.crypto.IncomingSecretShareRequest
|
||||
import im.vector.matrix.android.internal.crypto.IncomingShareRequestCommon
|
||||
import im.vector.matrix.android.internal.crypto.OutgoingGossipingRequest
|
||||
import im.vector.matrix.android.internal.crypto.OutgoingGossipingRequestState
|
||||
import im.vector.matrix.android.internal.crypto.OutgoingRoomKeyRequest
|
||||
import im.vector.matrix.android.internal.crypto.OutgoingSecretRequest
|
||||
import im.vector.matrix.android.internal.crypto.crosssigning.DeviceTrustLevel
|
||||
import im.vector.matrix.android.internal.crypto.model.CryptoCrossSigningKey
|
||||
import im.vector.matrix.android.internal.crypto.model.CryptoDeviceInfo
|
||||
import im.vector.matrix.android.internal.crypto.model.rest.RoomKeyRequestBody
|
||||
import im.vector.matrix.android.internal.di.MoshiProvider
|
||||
import im.vector.matrix.android.internal.di.SerializeNulls
|
||||
import im.vector.matrix.sqldelight.crypto.CrossSigningInfoEntity
|
||||
import im.vector.matrix.sqldelight.crypto.DeviceInfoEntity
|
||||
import im.vector.matrix.sqldelight.crypto.GetByUserId
|
||||
import im.vector.matrix.sqldelight.crypto.IncomingGossipingRequestEntity
|
||||
import im.vector.matrix.sqldelight.crypto.OutgoingGossipingRequestEntity
|
||||
import timber.log.Timber
|
||||
|
||||
object SqliteCryptoMapper {
|
||||
|
||||
private val moshi = Moshi.Builder().add(SerializeNulls.JSON_ADAPTER_FACTORY).build()
|
||||
private val listMigrationAdapter = moshi.adapter<List<String>>(Types.newParameterizedType(
|
||||
List::class.java,
|
||||
String::class.java,
|
||||
Any::class.java
|
||||
))
|
||||
private val mapMigrationAdapter = moshi.adapter<JsonDict>(Types.newParameterizedType(
|
||||
Map::class.java,
|
||||
String::class.java,
|
||||
Any::class.java
|
||||
))
|
||||
private val mapOfStringMigrationAdapter = moshi.adapter<Map<String, Map<String, String>>>(Types.newParameterizedType(
|
||||
Map::class.java,
|
||||
String::class.java,
|
||||
Any::class.java
|
||||
))
|
||||
private val recipientsDataMapper: JsonAdapter<Map<String, List<String>>> =
|
||||
MoshiProvider
|
||||
.providesMoshi()
|
||||
.adapter<Map<String, List<String>>>(
|
||||
Types.newParameterizedType(Map::class.java, String::class.java, List::class.java)
|
||||
)
|
||||
|
||||
internal fun mapToEntity(deviceInfo: CryptoDeviceInfo): DeviceInfoEntity {
|
||||
return DeviceInfoEntity.Impl(
|
||||
user_id = deviceInfo.userId,
|
||||
device_id = deviceInfo.deviceId,
|
||||
identity_key = deviceInfo.identityKey(),
|
||||
algorithm_list_json = listMigrationAdapter.toJson(deviceInfo.algorithms),
|
||||
keys_map_json = mapMigrationAdapter.toJson(deviceInfo.keys),
|
||||
signature_map_json = mapMigrationAdapter.toJson(deviceInfo.signatures),
|
||||
is_blocked = deviceInfo.isBlocked,
|
||||
locally_verified = deviceInfo.trustLevel?.locallyVerified == true,
|
||||
cross_signed_verified = deviceInfo.trustLevel?.crossSigningVerified == true,
|
||||
unsigned_map_json = mapMigrationAdapter.toJson(deviceInfo.unsigned)
|
||||
)
|
||||
}
|
||||
|
||||
internal fun mapToModel(deviceInfoEntity: DeviceInfoEntity): CryptoDeviceInfo {
|
||||
return CryptoDeviceInfo(
|
||||
deviceId = deviceInfoEntity.device_id,
|
||||
userId = deviceInfoEntity.user_id,
|
||||
algorithms = deviceInfoEntity.algorithm_list_json?.let {
|
||||
try {
|
||||
listMigrationAdapter.fromJson(it)
|
||||
} catch (failure: Throwable) {
|
||||
Timber.e(failure)
|
||||
null
|
||||
}
|
||||
},
|
||||
keys = deviceInfoEntity.keys_map_json?.let {
|
||||
try {
|
||||
moshi.adapter<Map<String, String>>(Types.newParameterizedType(
|
||||
Map::class.java,
|
||||
String::class.java,
|
||||
Any::class.java
|
||||
)).fromJson(it)
|
||||
} catch (failure: Throwable) {
|
||||
Timber.e(failure)
|
||||
null
|
||||
}
|
||||
},
|
||||
signatures = deviceInfoEntity.signature_map_json?.let {
|
||||
try {
|
||||
mapOfStringMigrationAdapter.fromJson(it)
|
||||
} catch (failure: Throwable) {
|
||||
Timber.e(failure)
|
||||
null
|
||||
}
|
||||
},
|
||||
unsigned = deviceInfoEntity.unsigned_map_json?.let {
|
||||
try {
|
||||
mapMigrationAdapter.fromJson(it)
|
||||
} catch (failure: Throwable) {
|
||||
Timber.e(failure)
|
||||
null
|
||||
}
|
||||
},
|
||||
trustLevel = DeviceTrustLevel(deviceInfoEntity.cross_signed_verified, deviceInfoEntity.locally_verified),
|
||||
isBlocked = deviceInfoEntity.is_blocked
|
||||
)
|
||||
}
|
||||
|
||||
internal fun mapToModel(crossSigningInfoEntity: GetByUserId): CryptoCrossSigningKey {
|
||||
val pubKey = crossSigningInfoEntity.public_key_base64 ?: ""
|
||||
return CryptoCrossSigningKey(
|
||||
userId = crossSigningInfoEntity.user_id,
|
||||
signatures = crossSigningInfoEntity.signatures?.let { deserializeSignaturesFromSqlite(it) },
|
||||
trustLevel = DeviceTrustLevel(
|
||||
crossSigningInfoEntity.cross_signed_verified,
|
||||
crossSigningInfoEntity.locally_verified
|
||||
),
|
||||
keys = mapOf("ed25519:$pubKey" to pubKey),
|
||||
usages = crossSigningInfoEntity.usages
|
||||
)
|
||||
}
|
||||
|
||||
internal fun mapToEntity(cryptoCrossSigningKey: CryptoCrossSigningKey): CrossSigningInfoEntity {
|
||||
return CrossSigningInfoEntity.Impl(
|
||||
user_id = cryptoCrossSigningKey.userId,
|
||||
signatures = serializeSignaturesForSqlite(cryptoCrossSigningKey.signatures),
|
||||
public_key_base64 = cryptoCrossSigningKey.unpaddedBase64PublicKey,
|
||||
usages = cryptoCrossSigningKey.usages ?: emptyList(),
|
||||
locally_verified = false,
|
||||
cross_signed_verified = false
|
||||
)
|
||||
}
|
||||
|
||||
fun serializeSignaturesForSqlite(signatures: Map<String, Map<String, String>>?): String {
|
||||
return mapMigrationAdapter.toJson(signatures)
|
||||
}
|
||||
|
||||
fun deserializeSignaturesFromSqlite(signatures: String):Map<String, Map<String, String>>? {
|
||||
return try {
|
||||
mapOfStringMigrationAdapter.fromJson(signatures)
|
||||
} catch (failure: Throwable) {
|
||||
Timber.e(failure)
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
fun toOutgoingGossipingRequest(entity: OutgoingGossipingRequestEntity): OutgoingGossipingRequest {
|
||||
return when (entity.type) {
|
||||
GossipRequestType.KEY.name -> {
|
||||
OutgoingRoomKeyRequest(
|
||||
requestBody = getRequestedKeyInfo(entity.type, entity.requested_info),
|
||||
recipients = getRecipientsMap(entity) ?: emptyMap(),
|
||||
requestId = entity.request_id,
|
||||
state = tryThis { OutgoingGossipingRequestState.valueOf(entity.requested_info!!) }
|
||||
?: OutgoingGossipingRequestState.UNSENT
|
||||
)
|
||||
}
|
||||
GossipRequestType.SECRET.name -> {
|
||||
OutgoingSecretRequest(
|
||||
secretName = getRequestedSecretName(entity.type, entity.requested_info),
|
||||
recipients = getRecipientsMap(entity) ?: emptyMap(),
|
||||
requestId = entity.request_id,
|
||||
state = tryThis { OutgoingGossipingRequestState.valueOf(entity.requested_info!!) }
|
||||
?: OutgoingGossipingRequestState.UNSENT
|
||||
)
|
||||
}
|
||||
else -> OutgoingRoomKeyRequest(
|
||||
requestBody = getRequestedKeyInfo(entity.type, entity.requested_info),
|
||||
recipients = getRecipientsMap(entity) ?: emptyMap(),
|
||||
requestId = entity.request_id,
|
||||
state = OutgoingGossipingRequestState.UNSENT
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun toIncomingGossipingRequest(entity: IncomingGossipingRequestEntity): IncomingShareRequestCommon {
|
||||
return when (GossipRequestType.valueOf(entity.type)) {
|
||||
GossipRequestType.KEY -> {
|
||||
IncomingRoomKeyRequest(
|
||||
requestBody = getRequestedKeyInfo(entity.type, entity.requested_info_str),
|
||||
deviceId = entity.other_device_id,
|
||||
userId = entity.other_user_id,
|
||||
requestId = entity.request_id,
|
||||
state = entity.request_state?.let { GossipingRequestState.valueOf(it) }
|
||||
?: GossipingRequestState.NONE,
|
||||
localCreationTimestamp = entity.local_creation_timestamp
|
||||
)
|
||||
}
|
||||
GossipRequestType.SECRET -> {
|
||||
IncomingSecretShareRequest(
|
||||
secretName = getRequestedSecretName(entity.type, entity.requested_info_str),
|
||||
deviceId = entity.other_device_id,
|
||||
userId = entity.other_user_id,
|
||||
requestId = entity.request_id,
|
||||
localCreationTimestamp = entity.local_creation_timestamp
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun getRecipientsMap(entity: OutgoingGossipingRequestEntity): Map<String, List<String>>? {
|
||||
return entity.recipients_data?.let { recipientsDataMapper.fromJson(it) }
|
||||
}
|
||||
|
||||
fun getRecipientsData(recipients: Map<String, List<String>>): String? {
|
||||
return recipientsDataMapper.toJson(recipients)
|
||||
}
|
||||
|
||||
fun getRequestedKeyInfo(type: String, requestedInfoStr: String?): RoomKeyRequestBody? {
|
||||
return if (type == GossipRequestType.KEY.name) {
|
||||
RoomKeyRequestBody.fromJson(requestedInfoStr)
|
||||
} else null
|
||||
}
|
||||
|
||||
fun getRequestedSecretName(type: String, requestedInfoStr: String?): String? {
|
||||
return if (type == GossipRequestType.SECRET.name) {
|
||||
requestedInfoStr
|
||||
} else null
|
||||
}
|
||||
}
|
@ -0,0 +1,49 @@
|
||||
package im.vector.matrix.android.internal.crypto.store.db
|
||||
|
||||
import android.util.Base64
|
||||
import im.vector.matrix.android.internal.util.CompatUtil
|
||||
import java.io.ByteArrayInputStream
|
||||
import java.io.ByteArrayOutputStream
|
||||
import java.io.ObjectInputStream
|
||||
import java.io.ObjectOutputStream
|
||||
import java.util.zip.GZIPInputStream
|
||||
|
||||
/**
|
||||
* Serialize any Serializable object, zip it and convert to Base64 String
|
||||
*/
|
||||
fun serializeForSqlite(o: Any?): String? {
|
||||
if (o == null) {
|
||||
return null
|
||||
}
|
||||
|
||||
val baos = ByteArrayOutputStream()
|
||||
val gzis = CompatUtil.createGzipOutputStream(baos)
|
||||
val out = ObjectOutputStream(gzis)
|
||||
|
||||
out.writeObject(o)
|
||||
out.close()
|
||||
|
||||
return Base64.encodeToString(baos.toByteArray(), Base64.DEFAULT)
|
||||
}
|
||||
|
||||
/**
|
||||
* Do the opposite of serializeForSqlite.
|
||||
*/
|
||||
fun <T> deserializeFromSqlite(string: String?): T? {
|
||||
if (string == null) {
|
||||
return null
|
||||
}
|
||||
|
||||
val decodedB64 = Base64.decode(string.toByteArray(), Base64.DEFAULT)
|
||||
|
||||
val bais = ByteArrayInputStream(decodedB64)
|
||||
val gzis = GZIPInputStream(bais)
|
||||
val ois = ObjectInputStream(gzis)
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
val result = ois.readObject() as T
|
||||
|
||||
ois.close()
|
||||
|
||||
return result
|
||||
}
|
@ -0,0 +1,82 @@
|
||||
import kotlin.collections.List;
|
||||
|
||||
CREATE TABLE crossSigningInfoEntity (
|
||||
user_id TEXT NOT NULL,
|
||||
usages TEXT AS List<String> NOT NULL,
|
||||
public_key_base64 TEXT,
|
||||
signatures TEXT,
|
||||
cross_signed_verified INTEGER AS Boolean DEFAULT 0 NOT NULL,
|
||||
locally_verified INTEGER AS Boolean DEFAULT 0 NOT NULL,
|
||||
PRIMARY KEY(user_id, usages)
|
||||
);
|
||||
|
||||
insertOrUpdate:
|
||||
INSERT OR REPLACE INTO crossSigningInfoEntity VALUES ?;
|
||||
|
||||
getAll:
|
||||
SELECT * FROM crossSigningInfoEntity;
|
||||
|
||||
getByUserId:
|
||||
SELECT rowid AS _id,
|
||||
user_id,
|
||||
usages,
|
||||
public_key_base64,
|
||||
signatures,
|
||||
cross_signed_verified,
|
||||
locally_verified
|
||||
FROM crossSigningInfoEntity
|
||||
WHERE user_id = :userId;
|
||||
|
||||
updateLocallyVerifiedWithRowId:
|
||||
UPDATE crossSigningInfoEntity
|
||||
SET locally_verified = :locallyVerified
|
||||
WHERE rowid = :rowId;
|
||||
|
||||
updateLocallyVerified:
|
||||
UPDATE crossSigningInfoEntity
|
||||
SET locally_verified = :locallyVerified
|
||||
WHERE user_id = :userId;
|
||||
|
||||
updateCrossSignedVerified:
|
||||
UPDATE crossSigningInfoEntity
|
||||
SET cross_signed_verified = :crossSignedVerified
|
||||
WHERE user_id = :userId;
|
||||
|
||||
updateVerified:
|
||||
UPDATE crossSigningInfoEntity
|
||||
SET locally_verified = :locallyVerified,
|
||||
cross_signed_verified = :crossSignedVerified
|
||||
WHERE user_id = :userId;
|
||||
|
||||
updateSignatures:
|
||||
UPDATE crossSigningInfoEntity
|
||||
SET signatures = :signatures
|
||||
WHERE user_id = :userId;
|
||||
|
||||
updateSignaturesWithRowId:
|
||||
UPDATE crossSigningInfoEntity
|
||||
SET signatures = :signatures
|
||||
WHERE rowid = :rowId;
|
||||
|
||||
updateUsages:
|
||||
UPDATE crossSigningInfoEntity
|
||||
SET usages = :usages
|
||||
WHERE user_id = :userId;
|
||||
|
||||
updateUsagesWithRowId:
|
||||
UPDATE crossSigningInfoEntity
|
||||
SET usages = :usages
|
||||
WHERE rowid = :rowId;
|
||||
|
||||
clearOtherUserTrust:
|
||||
UPDATE crossSigningInfoEntity
|
||||
SET locally_verified = 0,
|
||||
cross_signed_verified = 0
|
||||
WHERE user_id != :userId;
|
||||
|
||||
deleteByUserId:
|
||||
DELETE FROM crossSigningInfoEntity
|
||||
WHERE user_id = :userId;
|
||||
|
||||
deleteAll:
|
||||
DELETE FROM crossSigningInfoEntity;
|
@ -0,0 +1,66 @@
|
||||
import java.lang.Boolean;
|
||||
|
||||
CREATE TABLE cryptoMetadataEntity (
|
||||
user_id TEXT PRIMARY KEY NOT NULL,
|
||||
device_id TEXT,
|
||||
olm_account_data TEXT,
|
||||
device_sync_token TEXT,
|
||||
global_blacklist_unverified_devices INTEGER AS Boolean DEFAULT 0 NOT NULL,
|
||||
backup_version TEXT,
|
||||
x_sign_master_private_key TEXT,
|
||||
x_sign_user_private_key TEXT,
|
||||
x_sign_self_signed_private_key TEXT,
|
||||
key_backup_recovery_key TEXT,
|
||||
key_backup_recovery_key_version TEXT
|
||||
);
|
||||
|
||||
insertOrUpdate:
|
||||
INSERT OR REPLACE INTO cryptoMetadataEntity VALUES ?;
|
||||
|
||||
getAll:
|
||||
SELECT * FROM cryptoMetadataEntity;
|
||||
|
||||
getByUserId:
|
||||
SELECT * FROM cryptoMetadataEntity
|
||||
WHERE user_id = :userId;
|
||||
|
||||
count:
|
||||
SELECT COUNT(*) FROM cryptoMetadataEntity;
|
||||
|
||||
updateOlmAccountData:
|
||||
UPDATE cryptoMetadataEntity
|
||||
SET olm_account_data = :olmAccountData;
|
||||
|
||||
updateGlobalBlacklistUnverifiedDevices:
|
||||
UPDATE cryptoMetadataEntity
|
||||
SET global_blacklist_unverified_devices = :globalBlacklistUnverifiedDevices;
|
||||
|
||||
updateKeyBackupVersion:
|
||||
UPDATE cryptoMetadataEntity
|
||||
SET backup_version = :backupVersion;
|
||||
|
||||
updateDeviceId:
|
||||
UPDATE cryptoMetadataEntity
|
||||
SET device_id = :deviceId;
|
||||
|
||||
updateKeys:
|
||||
UPDATE cryptoMetadataEntity
|
||||
SET x_sign_master_private_key = :xSignMasterPrivateKey,
|
||||
x_sign_user_private_key = :xSignUserPrivateKey,
|
||||
x_sign_self_signed_private_key = :xSignSelfSignedPrivateKey;
|
||||
|
||||
updateSelfSignedPrivateKey:
|
||||
UPDATE cryptoMetadataEntity
|
||||
SET x_sign_self_signed_private_key = :xSignSelfSignedPrivateKey;
|
||||
|
||||
updateUserPrivateKey:
|
||||
UPDATE cryptoMetadataEntity
|
||||
SET x_sign_user_private_key = :xSignUserPrivateKey;
|
||||
|
||||
updateKeyBackupRecoveryKey:
|
||||
UPDATE cryptoMetadataEntity
|
||||
SET key_backup_recovery_key = :keyBackupRecoveryKey,
|
||||
key_backup_recovery_key_version = :keyBackupRecoveryKeyVersion;
|
||||
|
||||
deleteAll:
|
||||
DELETE FROM cryptoMetadataEntity;
|
@ -0,0 +1,50 @@
|
||||
import java.lang.Boolean;
|
||||
|
||||
CREATE TABLE cryptoRoomEntity (
|
||||
room_id TEXT NOT NULL PRIMARY KEY,
|
||||
algorithm TEXT,
|
||||
should_encrypt_for_invited_members INTEGER AS Boolean DEFAULT 0 NOT NULL,
|
||||
blacklist_unverified_devices INTEGER AS Boolean DEFAULT 0 NOT NULL
|
||||
);
|
||||
|
||||
insertOrUpdate:
|
||||
INSERT OR REPLACE INTO cryptoRoomEntity VALUES ?;
|
||||
|
||||
getAll:
|
||||
SELECT * FROM cryptoRoomEntity;
|
||||
|
||||
getById:
|
||||
SELECT * FROM cryptoRoomEntity
|
||||
WHERE room_id = :roomId;
|
||||
|
||||
getBlacklistUnverifiedDevices:
|
||||
SELECT * FROM cryptoRoomEntity
|
||||
WHERE blacklist_unverified_devices = :blacklistUnverifiedDevices;
|
||||
|
||||
getRoomAlgorithm:
|
||||
SELECT algorithm
|
||||
FROM cryptoRoomEntity
|
||||
WHERE room_id = :roomId;
|
||||
|
||||
shouldEncryptForInvitedMembers:
|
||||
SELECT should_encrypt_for_invited_members
|
||||
FROM cryptoRoomEntity
|
||||
WHERE room_id = :roomId;
|
||||
|
||||
updateShouldEncryptForInvitedMembers:
|
||||
UPDATE cryptoRoomEntity
|
||||
SET should_encrypt_for_invited_members = :shouldEncryptForInvitedMembers
|
||||
WHERE room_id = :roomId;
|
||||
|
||||
updateBlacklistUnverifiedDevices:
|
||||
UPDATE cryptoRoomEntity
|
||||
SET blacklist_unverified_devices = :blacklistUnverifiedDevices
|
||||
WHERE room_id = :roomId;
|
||||
|
||||
updateRoomAlgorithm:
|
||||
UPDATE cryptoRoomEntity
|
||||
SET algorithm = :algorithm
|
||||
WHERE room_id = :roomId;
|
||||
|
||||
deleteAll:
|
||||
DELETE FROM cryptoRoomEntity;
|
@ -0,0 +1,23 @@
|
||||
import java.lang.Integer;
|
||||
|
||||
CREATE TABLE cryptoUserEntity (
|
||||
user_id TEXT NOT NULL PRIMARY KEY,
|
||||
device_tracking_status INTEGER AS Integer DEFAULT 0 NOT NULL
|
||||
);
|
||||
|
||||
insertOrUpdate:
|
||||
INSERT OR REPLACE INTO cryptoUserEntity VALUES ?;
|
||||
|
||||
getAll:
|
||||
SELECT * FROM cryptoUserEntity;
|
||||
|
||||
getByUserId:
|
||||
SELECT * FROM cryptoUserEntity
|
||||
WHERE user_id = :userId;
|
||||
|
||||
deleteByUserId:
|
||||
DELETE FROM cryptoUserEntity
|
||||
WHERE user_id = :userId;
|
||||
|
||||
deleteAll:
|
||||
DELETE FROM cryptoUserEntity;
|
@ -0,0 +1,56 @@
|
||||
import java.lang.Boolean;
|
||||
|
||||
CREATE TABLE deviceInfoEntity (
|
||||
user_id TEXT NOT NULL,
|
||||
device_id TEXT NOT NULL,
|
||||
identity_key TEXT,
|
||||
is_blocked INTEGER AS Boolean DEFAULT 0 NOT NULL,
|
||||
algorithm_list_json TEXT,
|
||||
keys_map_json TEXT,
|
||||
signature_map_json TEXT,
|
||||
unsigned_map_json TEXT,
|
||||
cross_signed_verified INTEGER AS Boolean DEFAULT 0 NOT NULL,
|
||||
locally_verified INTEGER AS Boolean DEFAULT 0 NOT NULL,
|
||||
PRIMARY KEY(user_id, device_id)
|
||||
);
|
||||
|
||||
insertOrUpdate:
|
||||
INSERT OR REPLACE INTO deviceInfoEntity VALUES ?;
|
||||
|
||||
getAll:
|
||||
SELECT * FROM deviceInfoEntity;
|
||||
|
||||
getByUserIdAndDeviceId:
|
||||
SELECT * FROM deviceInfoEntity
|
||||
WHERE user_id = :userId
|
||||
AND device_id = :deviceId;
|
||||
|
||||
getByUserId:
|
||||
SELECT * FROM deviceInfoEntity
|
||||
WHERE user_id = :userId;
|
||||
|
||||
getByIdentityKey:
|
||||
SELECT * FROM deviceInfoEntity
|
||||
WHERE identity_key = :identityKey;
|
||||
|
||||
updateLocallyVerified:
|
||||
UPDATE deviceInfoEntity
|
||||
SET locally_verified = :locallyVerified
|
||||
WHERE user_id = :userId
|
||||
AND device_id = :deviceId;
|
||||
|
||||
updateCrossSignedVerified:
|
||||
UPDATE deviceInfoEntity
|
||||
SET cross_signed_verified = :crossSignedVerified
|
||||
WHERE user_id = :userId
|
||||
AND device_id = :deviceId;
|
||||
|
||||
updateVerified:
|
||||
UPDATE deviceInfoEntity
|
||||
SET locally_verified = :locallyVerified,
|
||||
cross_signed_verified = :crossSignedVerified
|
||||
WHERE user_id = :userId
|
||||
AND device_id = :deviceId;
|
||||
|
||||
deleteAll:
|
||||
DELETE FROM deviceInfoEntity;
|
@ -0,0 +1,31 @@
|
||||
import java.lang.Long;
|
||||
|
||||
CREATE TABLE gossipingEventEntity (
|
||||
type TEXT NOT NULL,
|
||||
sender TEXT NOT NULL,
|
||||
send_state TEXT,
|
||||
content TEXT,
|
||||
decryption_result_json TEXT,
|
||||
decryption_error_code TEXT,
|
||||
age_local_ts INTEGER AS Long DEFAULT 0 NOT NULL
|
||||
);
|
||||
|
||||
CREATE INDEX gossiping_event_type ON gossipingEventEntity(type);
|
||||
CREATE INDEX gossiping_event_sender ON gossipingEventEntity(sender);
|
||||
|
||||
insertOrUpdate:
|
||||
INSERT OR REPLACE INTO gossipingEventEntity VALUES ?;
|
||||
|
||||
getAll:
|
||||
SELECT * FROM gossipingEventEntity;
|
||||
|
||||
getByType:
|
||||
SELECT * FROM gossipingEventEntity
|
||||
WHERE type = :type;
|
||||
|
||||
getBySender:
|
||||
SELECT * FROM gossipingEventEntity
|
||||
WHERE sender = :sender;
|
||||
|
||||
deleteAll:
|
||||
DELETE FROM gossipingEventEntity;
|
@ -0,0 +1,49 @@
|
||||
import java.lang.Long;
|
||||
|
||||
CREATE TABLE incomingGossipingRequestEntity (
|
||||
request_id TEXT NOT NULL,
|
||||
type TEXT NOT NULL,
|
||||
other_user_id TEXT,
|
||||
requested_info_str TEXT,
|
||||
request_state TEXT,
|
||||
other_device_id TEXT,
|
||||
local_creation_timestamp INTEGER AS Long DEFAULT 0 NOT NULL
|
||||
);
|
||||
|
||||
CREATE INDEX incoming_gossiping_request_request_id ON incomingGossipingRequestEntity(request_id);
|
||||
CREATE INDEX incoming_gossiping_request_type ON incomingGossipingRequestEntity(type);
|
||||
|
||||
insertOrUpdate:
|
||||
INSERT OR REPLACE INTO incomingGossipingRequestEntity VALUES ?;
|
||||
|
||||
getAll:
|
||||
SELECT * FROM incomingGossipingRequestEntity;
|
||||
|
||||
getByType:
|
||||
SELECT * FROM incomingGossipingRequestEntity
|
||||
WHERE type = :type;
|
||||
|
||||
getByRequestState:
|
||||
SELECT * FROM incomingGossipingRequestEntity
|
||||
WHERE request_state = :requestState;
|
||||
|
||||
getByTypeAndRequestState:
|
||||
SELECT * FROM incomingGossipingRequestEntity
|
||||
WHERE type = :type
|
||||
AND request_state = :requestState;
|
||||
|
||||
getIncomingRoomKeyRequest:
|
||||
SELECT * FROM incomingGossipingRequestEntity
|
||||
WHERE type = :type
|
||||
AND other_user_id = :otherUserId
|
||||
AND other_device_id = :otherDeviceId;
|
||||
|
||||
updateRequestState:
|
||||
UPDATE incomingGossipingRequestEntity
|
||||
SET request_state = :requestState
|
||||
WHERE other_user_id = :otherUserId
|
||||
AND other_device_id = :otherDeviceId
|
||||
AND request_id = :requestId;
|
||||
|
||||
deleteAll:
|
||||
DELETE FROM incomingGossipingRequestEntity;
|
@ -0,0 +1,14 @@
|
||||
CREATE TABLE keysBackupDataEntity (
|
||||
static_id INTEGER PRIMARY KEY CHECK (static_id = 0),
|
||||
backup_last_server_hash TEXT,
|
||||
backup_last_server_number_of_keys INTEGER DEFAULT 0 NOT NULL
|
||||
);
|
||||
|
||||
insertOrUpdate:
|
||||
INSERT OR REPLACE INTO keysBackupDataEntity VALUES ?;
|
||||
|
||||
getAll:
|
||||
SELECT * FROM keysBackupDataEntity;
|
||||
|
||||
deleteAll:
|
||||
DELETE FROM keysBackupDataEntity;
|
@ -0,0 +1,52 @@
|
||||
import java.lang.Boolean;
|
||||
|
||||
CREATE TABLE olmInboundGroupSessionEntity (
|
||||
session_id TEXT NOT NULL,
|
||||
sender_key TEXT NOT NULL,
|
||||
olm_inbound_group_session_data TEXT,
|
||||
backed_up INTEGER AS Boolean DEFAULT 0 NOT NULL,
|
||||
PRIMARY KEY(session_id, sender_key)
|
||||
);
|
||||
|
||||
insertOrUpdate:
|
||||
INSERT OR REPLACE INTO olmInboundGroupSessionEntity VALUES ?;
|
||||
|
||||
getAll:
|
||||
SELECT * FROM olmInboundGroupSessionEntity;
|
||||
|
||||
getBySessionIdAndSenderKey:
|
||||
SELECT * FROM olmInboundGroupSessionEntity
|
||||
WHERE session_id = :sessionId
|
||||
AND sender_key = :senderKey;
|
||||
|
||||
getAllBackedUp:
|
||||
SELECT * FROM olmInboundGroupSessionEntity
|
||||
WHERE backed_up = :isbackedUp
|
||||
LIMIT :limit;
|
||||
|
||||
countAll:
|
||||
SELECT COUNT(*)
|
||||
FROM olmInboundGroupSessionEntity;
|
||||
|
||||
countBackedUp:
|
||||
SELECT COUNT(*)
|
||||
FROM olmInboundGroupSessionEntity
|
||||
WHERE backed_up = :backedUp;
|
||||
|
||||
deleteBySessionIdAndSenderKey:
|
||||
DELETE FROM olmInboundGroupSessionEntity
|
||||
WHERE session_id = :sessionId
|
||||
AND sender_key = :senderKey;
|
||||
|
||||
setAllBackedUp:
|
||||
UPDATE olmInboundGroupSessionEntity
|
||||
SET backed_up = :isBackedUp;
|
||||
|
||||
setBackedUp:
|
||||
UPDATE olmInboundGroupSessionEntity
|
||||
SET backed_up = :isBackedUp
|
||||
WHERE session_id = :sessionId
|
||||
AND sender_key = :senderKey;
|
||||
|
||||
deleteAll:
|
||||
DELETE FROM olmInboundGroupSessionEntity;
|
@ -0,0 +1,34 @@
|
||||
import java.lang.Long;
|
||||
|
||||
CREATE TABLE olmSessionEntity (
|
||||
session_id TEXT NOT NULL,
|
||||
device_key TEXT NOT NULL,
|
||||
olm_session_data TEXT,
|
||||
last_received_message_ts INTEGER AS Long DEFAULT 0 NOT NULL,
|
||||
PRIMARY KEY(session_id, device_key)
|
||||
);
|
||||
|
||||
CREATE INDEX olm_session_device_key ON olmSessionEntity(device_key);
|
||||
|
||||
insertOrUpdate:
|
||||
INSERT OR REPLACE INTO olmSessionEntity VALUES ?;
|
||||
|
||||
getAll:
|
||||
SELECT * FROM olmSessionEntity;
|
||||
|
||||
getBySessionIdAndDeviceKey:
|
||||
SELECT * FROM olmSessionEntity
|
||||
WHERE session_id = :sessionId
|
||||
AND device_key = :deviceKey;
|
||||
|
||||
getByDeviceKey:
|
||||
SELECT * FROM olmSessionEntity
|
||||
WHERE device_key = :deviceKey;
|
||||
|
||||
getByDeviceKeyDescending:
|
||||
SELECT * FROM olmSessionEntity
|
||||
WHERE device_key = :deviceKey
|
||||
ORDER BY last_received_message_ts DESC;
|
||||
|
||||
deleteAll:
|
||||
DELETE FROM olmSessionEntity;
|
@ -0,0 +1,37 @@
|
||||
CREATE TABLE outgoingGossipingRequestEntity (
|
||||
request_id TEXT NOT NULL,
|
||||
type TEXT NOT NULL,
|
||||
recipients_data TEXT,
|
||||
requested_info TEXT,
|
||||
request_state TEXT
|
||||
);
|
||||
|
||||
CREATE INDEX outgoing_gossiping_request_request_id ON outgoingGossipingRequestEntity(request_id);
|
||||
CREATE INDEX outgoing_gossiping_request_type ON outgoingGossipingRequestEntity(type);
|
||||
|
||||
insertOrUpdate:
|
||||
INSERT OR REPLACE INTO outgoingGossipingRequestEntity VALUES ?;
|
||||
|
||||
getAll:
|
||||
SELECT * FROM outgoingGossipingRequestEntity;
|
||||
|
||||
getByRequestId:
|
||||
SELECT * FROM outgoingGossipingRequestEntity
|
||||
WHERE request_id = :requestId;
|
||||
|
||||
getByType:
|
||||
SELECT * FROM outgoingGossipingRequestEntity
|
||||
WHERE type = :type;
|
||||
|
||||
getByTypeAndRequestedInfo:
|
||||
SELECT * FROM outgoingGossipingRequestEntity
|
||||
WHERE type = :type
|
||||
AND requested_info = :requestedInfo;
|
||||
|
||||
updateRequestState:
|
||||
UPDATE outgoingGossipingRequestEntity
|
||||
SET request_state = :requestState
|
||||
WHERE request_id = :requestId;
|
||||
|
||||
deleteAll:
|
||||
DELETE FROM outgoingGossipingRequestEntity;
|
@ -1,2 +1,3 @@
|
||||
include ':vector', ':matrix-sdk-android', ':matrix-sdk-android-rx', ':diff-match-patch', ':matrix-sdk-sqldelight'
|
||||
include ':multipicker'
|
||||
include ':matrix-sdk-sqldelight'
|
||||
|
Loading…
x
Reference in New Issue
Block a user