mirror of
https://github.com/SchildiChat/SchildiChat-android.git
synced 2025-02-17 20:40:07 +03:00
Merge pull request #8366 from vector-im/feature/bca/rust_integration_test_wf
add workflow for rust test
This commit is contained in:
commit
e7c122ef1d
12 changed files with 288 additions and 73 deletions
102
.github/workflows/tests-rust.yml
vendored
Normal file
102
.github/workflows/tests-rust.yml
vendored
Normal file
|
@ -0,0 +1,102 @@
|
||||||
|
name: Test
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request: { }
|
||||||
|
push:
|
||||||
|
branches: [ main, develop ]
|
||||||
|
paths-ignore:
|
||||||
|
- '.github/**'
|
||||||
|
|
||||||
|
# Enrich gradle.properties for CI/CD
|
||||||
|
env:
|
||||||
|
GRADLE_OPTS: -Dorg.gradle.jvmargs="-Xmx3072m -Dfile.encoding=UTF-8 -XX:+HeapDumpOnOutOfMemoryError" -Dkotlin.daemon.jvm.options="-Xmx2560m" -Dkotlin.incremental=false
|
||||||
|
CI_GRADLE_ARG_PROPERTIES: --stacktrace -PpreDexEnable=false --max-workers 4 --no-daemon
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
tests:
|
||||||
|
name: Runs all tests with rust crypto
|
||||||
|
runs-on: buildjet-4vcpu-ubuntu-2204
|
||||||
|
timeout-minutes: 90 # We might need to increase it if the time for tests grows
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
api-level: [28]
|
||||||
|
# Allow all jobs on main and develop. Just one per PR.
|
||||||
|
concurrency:
|
||||||
|
group: ${{ github.ref == 'refs/heads/main' && format('unit-tests-main-rust-{0}', github.sha) || github.ref == 'refs/heads/develop' && format('unit-tests-develop-rust-{0}', github.sha) || format('unit-tests-rust-{0}', github.ref) }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
lfs: true
|
||||||
|
fetch-depth: 0
|
||||||
|
- uses: actions/setup-java@v3
|
||||||
|
with:
|
||||||
|
distribution: 'adopt'
|
||||||
|
java-version: '11'
|
||||||
|
- uses: gradle/gradle-build-action@v2
|
||||||
|
with:
|
||||||
|
cache-read-only: ${{ github.ref != 'refs/heads/develop' }}
|
||||||
|
gradle-home-cache-cleanup: ${{ github.ref == 'refs/heads/develop' }}
|
||||||
|
|
||||||
|
# - name: Run screenshot tests
|
||||||
|
# run: ./gradlew verifyScreenshots $CI_GRADLE_ARG_PROPERTIES
|
||||||
|
|
||||||
|
# - name: Archive Screenshot Results on Error
|
||||||
|
# if: failure()
|
||||||
|
# uses: actions/upload-artifact@v3
|
||||||
|
# with:
|
||||||
|
# name: screenshot-results
|
||||||
|
# path: |
|
||||||
|
# **/out/failures/
|
||||||
|
# **/build/reports/tests/*UnitTest/
|
||||||
|
|
||||||
|
- uses: actions/setup-python@v4
|
||||||
|
with:
|
||||||
|
python-version: 3.8
|
||||||
|
- uses: michaelkaye/setup-matrix-synapse@v1.0.4
|
||||||
|
with:
|
||||||
|
uploadLogs: true
|
||||||
|
httpPort: 8080
|
||||||
|
disableRateLimiting: true
|
||||||
|
public_baseurl: "http://10.0.2.2:8080/"
|
||||||
|
|
||||||
|
- name: Run all the codecoverage tests at once
|
||||||
|
uses: reactivecircus/android-emulator-runner@v2
|
||||||
|
# continue-on-error: true
|
||||||
|
with:
|
||||||
|
api-level: ${{ matrix.api-level }}
|
||||||
|
arch: x86
|
||||||
|
profile: Nexus 5X
|
||||||
|
target: playstore
|
||||||
|
force-avd-creation: false
|
||||||
|
emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
|
||||||
|
disable-animations: true
|
||||||
|
# emulator-build: 7425822
|
||||||
|
script: |
|
||||||
|
./gradlew gatherGplayRustCryptoDebugStringTemplates $CI_GRADLE_ARG_PROPERTIES
|
||||||
|
./gradlew instrumentationTestsRustWithCoverage $CI_GRADLE_ARG_PROPERTIES
|
||||||
|
./gradlew generateCoverageReport $CI_GRADLE_ARG_PROPERTIES
|
||||||
|
|
||||||
|
- name: Upload Rust Integration Test Report Log
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
if: always()
|
||||||
|
with:
|
||||||
|
name: integration-test-rust-error-results
|
||||||
|
path: |
|
||||||
|
*/build/outputs/androidTest-results/connected/
|
||||||
|
*/build/reports/androidTests/connected/
|
||||||
|
|
||||||
|
# For now ignore sonar
|
||||||
|
# - name: Publish results to Sonar
|
||||||
|
# env:
|
||||||
|
# GITHUB_TOKEN: ${{ secrets.SONARQUBE_GITHUB_API_TOKEN }} # Needed to get PR information, if any
|
||||||
|
# SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
|
||||||
|
# ORG_GRADLE_PROJECT_SONAR_LOGIN: ${{ secrets.SONAR_TOKEN }}
|
||||||
|
# if: ${{ always() && env.GITHUB_TOKEN != '' && env.SONAR_TOKEN != '' && env.ORG_GRADLE_PROJECT_SONAR_LOGIN != '' }}
|
||||||
|
# run: ./gradlew sonar $CI_GRADLE_ARG_PROPERTIES
|
||||||
|
|
||||||
|
- name: Format unit test results
|
||||||
|
if: always()
|
||||||
|
run: python3 ./tools/ci/render_test_output.py unit ./**/build/test-results/**/*.xml
|
||||||
|
|
||||||
|
|
1
changelog.d/8366.misc
Normal file
1
changelog.d/8366.misc
Normal file
|
@ -0,0 +1 @@
|
||||||
|
CI: Add workflow to run test with crypto flavor
|
|
@ -89,3 +89,9 @@ task instrumentationTestsWithCoverage(type: GradleBuild) {
|
||||||
startParameter.projectProperties['android.testInstrumentationRunnerArguments.notPackage'] = 'im.vector.app.ui'
|
startParameter.projectProperties['android.testInstrumentationRunnerArguments.notPackage'] = 'im.vector.app.ui'
|
||||||
tasks = [':vector-app:connectedGplayKotlinCryptoDebugAndroidTest', ':vector:connectedKotlinCryptoDebugAndroidTest', 'matrix-sdk-android:connectedKotlinCryptoDebugAndroidTest']
|
tasks = [':vector-app:connectedGplayKotlinCryptoDebugAndroidTest', ':vector:connectedKotlinCryptoDebugAndroidTest', 'matrix-sdk-android:connectedKotlinCryptoDebugAndroidTest']
|
||||||
}
|
}
|
||||||
|
|
||||||
|
task instrumentationTestsRustWithCoverage(type: GradleBuild) {
|
||||||
|
startParameter.projectProperties.coverage = "true"
|
||||||
|
startParameter.projectProperties['android.testInstrumentationRunnerArguments.notPackage'] = 'im.vector.app.ui'
|
||||||
|
tasks = [':vector-app:connectedGplayRustCryptoDebugAndroidTest', ':vector:connectedRustCryptoDebugAndroidTest', 'matrix-sdk-android:connectedRustCryptoDebugAndroidTest']
|
||||||
|
}
|
||||||
|
|
|
@ -216,7 +216,7 @@ dependencies {
|
||||||
|
|
||||||
implementation libs.google.phonenumber
|
implementation libs.google.phonenumber
|
||||||
|
|
||||||
rustCryptoImplementation("org.matrix.rustcomponents:crypto-android:0.3.5")
|
rustCryptoImplementation("org.matrix.rustcomponents:crypto-android:0.3.7")
|
||||||
// rustCryptoApi project(":library:rustCrypto")
|
// rustCryptoApi project(":library:rustCrypto")
|
||||||
|
|
||||||
testImplementation libs.tests.junit
|
testImplementation libs.tests.junit
|
||||||
|
|
|
@ -26,6 +26,7 @@ import org.junit.Assert.assertEquals
|
||||||
import org.junit.Assert.assertFalse
|
import org.junit.Assert.assertFalse
|
||||||
import org.junit.Assert.assertNotNull
|
import org.junit.Assert.assertNotNull
|
||||||
import org.junit.Assert.assertTrue
|
import org.junit.Assert.assertTrue
|
||||||
|
import org.junit.Assume
|
||||||
import org.junit.FixMethodOrder
|
import org.junit.FixMethodOrder
|
||||||
import org.junit.Ignore
|
import org.junit.Ignore
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
|
@ -128,6 +129,7 @@ class KeysBackupTest : InstrumentedTest {
|
||||||
@Test
|
@Test
|
||||||
fun createKeysBackupVersionTest() = runCryptoTest(context()) { cryptoTestHelper, testHelper ->
|
fun createKeysBackupVersionTest() = runCryptoTest(context()) { cryptoTestHelper, testHelper ->
|
||||||
val bobSession = testHelper.createAccount(TestConstants.USER_BOB, KeysBackupTestConstants.defaultSessionParams)
|
val bobSession = testHelper.createAccount(TestConstants.USER_BOB, KeysBackupTestConstants.defaultSessionParams)
|
||||||
|
Log.d("#E2E", "Initializing crosssigning for ${bobSession.myUserId.take(8)}")
|
||||||
cryptoTestHelper.initializeCrossSigning(bobSession)
|
cryptoTestHelper.initializeCrossSigning(bobSession)
|
||||||
|
|
||||||
val keysBackup = bobSession.cryptoService().keysBackupService()
|
val keysBackup = bobSession.cryptoService().keysBackupService()
|
||||||
|
@ -136,12 +138,14 @@ class KeysBackupTest : InstrumentedTest {
|
||||||
|
|
||||||
assertFalse(keysBackup.isEnabled())
|
assertFalse(keysBackup.isEnabled())
|
||||||
|
|
||||||
|
Log.d("#E2E", "prepareKeysBackupVersion")
|
||||||
val megolmBackupCreationInfo =
|
val megolmBackupCreationInfo =
|
||||||
keysBackup.prepareKeysBackupVersion(null, null)
|
keysBackup.prepareKeysBackupVersion(null, null)
|
||||||
|
|
||||||
assertFalse(keysBackup.isEnabled())
|
assertFalse(keysBackup.isEnabled())
|
||||||
|
|
||||||
// Create the version
|
// Create the version
|
||||||
|
Log.d("#E2E", "createKeysBackupVersion")
|
||||||
val version = keysBackup.createKeysBackupVersion(megolmBackupCreationInfo)
|
val version = keysBackup.createKeysBackupVersion(megolmBackupCreationInfo)
|
||||||
|
|
||||||
// Backup must be enable now
|
// Backup must be enable now
|
||||||
|
@ -151,6 +155,7 @@ class KeysBackupTest : InstrumentedTest {
|
||||||
val versionResult = keysBackup.getVersion(version.version)
|
val versionResult = keysBackup.getVersion(version.version)
|
||||||
val trust = keysBackup.getKeysBackupTrust(versionResult!!)
|
val trust = keysBackup.getKeysBackupTrust(versionResult!!)
|
||||||
|
|
||||||
|
Log.d("#E2E", "Check backup signatures")
|
||||||
assertEquals("Should have 2 signatures", 2, trust.signatures.size)
|
assertEquals("Should have 2 signatures", 2, trust.signatures.size)
|
||||||
|
|
||||||
trust.signatures
|
trust.signatures
|
||||||
|
@ -432,9 +437,13 @@ class KeysBackupTest : InstrumentedTest {
|
||||||
.keysBackupService()
|
.keysBackupService()
|
||||||
.getKeysBackupTrust(keysVersionResult)
|
.getKeysBackupTrust(keysVersionResult)
|
||||||
|
|
||||||
// - It must be trusted and must have 2 signatures now
|
// The backup should have a valid signature from that device now
|
||||||
assertTrue(keysBackupVersionTrust.usable)
|
assertTrue(keysBackupVersionTrust.usable)
|
||||||
assertEquals(2, keysBackupVersionTrust.signatures.size)
|
val signature = keysBackupVersionTrust.signatures
|
||||||
|
.filterIsInstance<KeysBackupVersionTrustSignature.DeviceSignature>()
|
||||||
|
.firstOrNull { it.deviceId == testData.aliceSession2.cryptoService().getMyCryptoDevice().deviceId }
|
||||||
|
assertNotNull(signature)
|
||||||
|
assertTrue(signature!!.valid)
|
||||||
|
|
||||||
stateObserver.stopAndCheckStates(null)
|
stateObserver.stopAndCheckStates(null)
|
||||||
}
|
}
|
||||||
|
@ -492,9 +501,16 @@ class KeysBackupTest : InstrumentedTest {
|
||||||
.keysBackupService()
|
.keysBackupService()
|
||||||
.getKeysBackupTrust(keysVersionResult)
|
.getKeysBackupTrust(keysVersionResult)
|
||||||
|
|
||||||
// - It must be trusted and must have 2 signatures now
|
// // - It must be trusted and must have 2 signatures now
|
||||||
|
// assertTrue(keysBackupVersionTrust.usable)
|
||||||
|
// assertEquals(2, keysBackupVersionTrust.signatures.size)
|
||||||
|
// The backup should have a valid signature from that device now
|
||||||
assertTrue(keysBackupVersionTrust.usable)
|
assertTrue(keysBackupVersionTrust.usable)
|
||||||
assertEquals(2, keysBackupVersionTrust.signatures.size)
|
val signature = keysBackupVersionTrust.signatures
|
||||||
|
.filterIsInstance<KeysBackupVersionTrustSignature.DeviceSignature>()
|
||||||
|
.firstOrNull { it.deviceId == testData.aliceSession2.cryptoService().getMyCryptoDevice().deviceId }
|
||||||
|
assertNotNull(signature)
|
||||||
|
assertTrue(signature!!.valid)
|
||||||
|
|
||||||
stateObserver.stopAndCheckStates(null)
|
stateObserver.stopAndCheckStates(null)
|
||||||
}
|
}
|
||||||
|
@ -590,9 +606,17 @@ class KeysBackupTest : InstrumentedTest {
|
||||||
.keysBackupService()
|
.keysBackupService()
|
||||||
.getKeysBackupTrust(keysVersionResult)
|
.getKeysBackupTrust(keysVersionResult)
|
||||||
|
|
||||||
// - It must be trusted and must have 2 signatures now
|
// // - It must be trusted and must have 2 signatures now
|
||||||
|
// assertTrue(keysBackupVersionTrust.usable)
|
||||||
|
// assertEquals(2, keysBackupVersionTrust.signatures.size)
|
||||||
|
|
||||||
|
// - It must be trusted and signed by current device
|
||||||
assertTrue(keysBackupVersionTrust.usable)
|
assertTrue(keysBackupVersionTrust.usable)
|
||||||
assertEquals(2, keysBackupVersionTrust.signatures.size)
|
val signature = keysBackupVersionTrust.signatures
|
||||||
|
.filterIsInstance<KeysBackupVersionTrustSignature.DeviceSignature>()
|
||||||
|
.firstOrNull { it.deviceId == testData.aliceSession2.cryptoService().getMyCryptoDevice().deviceId }
|
||||||
|
assertNotNull(signature)
|
||||||
|
assertTrue(signature!!.valid)
|
||||||
|
|
||||||
stateObserver.stopAndCheckStates(null)
|
stateObserver.stopAndCheckStates(null)
|
||||||
}
|
}
|
||||||
|
@ -672,11 +696,16 @@ class KeysBackupTest : InstrumentedTest {
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
fun testBackupWithPassword() = runCryptoTest(context()) { cryptoTestHelper, testHelper ->
|
fun testBackupWithPassword() = runCryptoTest(context()) { cryptoTestHelper, testHelper ->
|
||||||
|
|
||||||
val keysBackupTestHelper = KeysBackupTestHelper(testHelper, cryptoTestHelper)
|
val keysBackupTestHelper = KeysBackupTestHelper(testHelper, cryptoTestHelper)
|
||||||
|
|
||||||
val password = "password"
|
val password = "password"
|
||||||
|
|
||||||
val testData = keysBackupTestHelper.createKeysBackupScenarioWithPassword(password)
|
val testData = keysBackupTestHelper.createKeysBackupScenarioWithPassword(password)
|
||||||
|
Assume.assumeTrue(
|
||||||
|
"Can't report progress same way in rust",
|
||||||
|
testData.cryptoTestData.firstSession.cryptoService().name() != "rust-sdk"
|
||||||
|
)
|
||||||
|
|
||||||
// - Restore the e2e backup with the password
|
// - Restore the e2e backup with the password
|
||||||
val steps = ArrayList<StepProgressListener.Step>()
|
val steps = ArrayList<StepProgressListener.Step>()
|
||||||
|
@ -887,6 +916,7 @@ class KeysBackupTest : InstrumentedTest {
|
||||||
* -> It must success
|
* -> It must success
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
|
@Ignore("Instable on both flavors")
|
||||||
fun testBackupAfterVerifyingADevice() = runCryptoTest(context()) { cryptoTestHelper, testHelper ->
|
fun testBackupAfterVerifyingADevice() = runCryptoTest(context()) { cryptoTestHelper, testHelper ->
|
||||||
val keysBackupTestHelper = KeysBackupTestHelper(testHelper, cryptoTestHelper)
|
val keysBackupTestHelper = KeysBackupTestHelper(testHelper, cryptoTestHelper)
|
||||||
|
|
||||||
|
@ -930,9 +960,13 @@ class KeysBackupTest : InstrumentedTest {
|
||||||
assertEquals("Backup state must be NotTrusted", KeysBackupState.NotTrusted, keysBackup2.getState())
|
assertEquals("Backup state must be NotTrusted", KeysBackupState.NotTrusted, keysBackup2.getState())
|
||||||
assertFalse("Backup should not be enabled", keysBackup2.isEnabled())
|
assertFalse("Backup should not be enabled", keysBackup2.isEnabled())
|
||||||
|
|
||||||
|
val signatures = keysBackup2.getCurrentVersion()?.toKeysVersionResult()?.getAuthDataAsMegolmBackupAuthData()?.signatures
|
||||||
|
Log.d("#E2E", "keysBackup2 signatures: $signatures")
|
||||||
|
|
||||||
// - Validate the old device from the new one
|
// - Validate the old device from the new one
|
||||||
cryptoTestHelper.verifyNewSession(cryptoTestData.firstSession, aliceSession2)
|
cryptoTestHelper.verifyNewSession(cryptoTestData.firstSession, aliceSession2)
|
||||||
|
|
||||||
|
cryptoTestData.firstSession.cryptoService().keysBackupService().checkAndStartKeysBackup()
|
||||||
// -> Backup should automatically enable on the new device
|
// -> Backup should automatically enable on the new device
|
||||||
suspendCancellableCoroutine<Unit> { continuation ->
|
suspendCancellableCoroutine<Unit> { continuation ->
|
||||||
val listener = object : KeysBackupStateListener {
|
val listener = object : KeysBackupStateListener {
|
||||||
|
@ -954,11 +988,11 @@ class KeysBackupTest : InstrumentedTest {
|
||||||
assertEquals(oldKeyBackupVersion, aliceSession2.cryptoService().keysBackupService().currentBackupVersion)
|
assertEquals(oldKeyBackupVersion, aliceSession2.cryptoService().keysBackupService().currentBackupVersion)
|
||||||
|
|
||||||
// aliceSession2.cryptoService().keysBackupService().backupAllGroupSessions(null, it)
|
// aliceSession2.cryptoService().keysBackupService().backupAllGroupSessions(null, it)
|
||||||
testHelper.retryPeriodically {
|
testHelper.retryWithBackoff {
|
||||||
keysBackup2.getTotalNumbersOfKeys() == keysBackup2.getTotalNumbersOfBackedUpKeys()
|
keysBackup2.getTotalNumbersOfKeys() == keysBackup2.getTotalNumbersOfBackedUpKeys()
|
||||||
}
|
}
|
||||||
|
|
||||||
testHelper.retryPeriodically {
|
testHelper.retryWithBackoff {
|
||||||
aliceSession2.cryptoService().keysBackupService().getState() == KeysBackupState.ReadyToBackUp
|
aliceSession2.cryptoService().keysBackupService().getState() == KeysBackupState.ReadyToBackUp
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,6 +26,7 @@ import org.junit.After
|
||||||
import org.junit.Assert.assertNotNull
|
import org.junit.Assert.assertNotNull
|
||||||
import org.junit.Assert.assertTrue
|
import org.junit.Assert.assertTrue
|
||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
|
import org.junit.Ignore
|
||||||
import org.junit.Rule
|
import org.junit.Rule
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import org.junit.runner.RunWith
|
import org.junit.runner.RunWith
|
||||||
|
@ -65,6 +66,16 @@ class ElementAndroidToElementRMigrationTest : InstrumentedTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun given_a_valid_crypto_store_realm_file_then_migration_should_be_successful() {
|
fun given_a_valid_crypto_store_realm_file_then_migration_should_be_successful() {
|
||||||
|
testMigrate(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Ignore("We don't migrate group session for now, and it makes test suite unstable")
|
||||||
|
fun given_a_valid_crypto_store_realm_file_no_lazy_then_migration_should_be_successful() {
|
||||||
|
testMigrate(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun testMigrate(migrateGroupSessions: Boolean) {
|
||||||
val realmName = "crypto_store_migration_16.realm"
|
val realmName = "crypto_store_migration_16.realm"
|
||||||
val migration = RealmCryptoStoreMigration(object : Clock {
|
val migration = RealmCryptoStoreMigration(object : Clock {
|
||||||
override fun epochMillis() = 0L
|
override fun epochMillis() = 0L
|
||||||
|
@ -86,7 +97,7 @@ class ElementAndroidToElementRMigrationTest : InstrumentedTest {
|
||||||
val deviceId = metaData.deviceId!!
|
val deviceId = metaData.deviceId!!
|
||||||
val olmAccount = metaData.getOlmAccount()!!
|
val olmAccount = metaData.getOlmAccount()!!
|
||||||
|
|
||||||
val extractor = MigrateEAtoEROperation()
|
val extractor = MigrateEAtoEROperation(migrateGroupSessions)
|
||||||
|
|
||||||
val targetFile = File(configurationFactory.root, "rust-sdk")
|
val targetFile = File(configurationFactory.root, "rust-sdk")
|
||||||
|
|
||||||
|
@ -101,14 +112,16 @@ class ElementAndroidToElementRMigrationTest : InstrumentedTest {
|
||||||
assertTrue(crossSigningStatus.hasSelfSigning)
|
assertTrue(crossSigningStatus.hasSelfSigning)
|
||||||
assertTrue(crossSigningStatus.hasUserSigning)
|
assertTrue(crossSigningStatus.hasUserSigning)
|
||||||
|
|
||||||
val inboundGroupSessionEntities = realm!!.where<OlmInboundGroupSessionEntity>().findAll()
|
if (migrateGroupSessions) {
|
||||||
assertEquals(inboundGroupSessionEntities.size, machine.roomKeyCounts().total.toInt())
|
val inboundGroupSessionEntities = realm!!.where<OlmInboundGroupSessionEntity>().findAll()
|
||||||
|
assertEquals(inboundGroupSessionEntities.size, machine.roomKeyCounts().total.toInt())
|
||||||
|
|
||||||
val backedUpInboundGroupSessionEntities = realm!!
|
val backedUpInboundGroupSessionEntities = realm!!
|
||||||
.where<OlmInboundGroupSessionEntity>()
|
.where<OlmInboundGroupSessionEntity>()
|
||||||
.equalTo(OlmInboundGroupSessionEntityFields.BACKED_UP, true)
|
.equalTo(OlmInboundGroupSessionEntityFields.BACKED_UP, true)
|
||||||
.findAll()
|
.findAll()
|
||||||
assertEquals(backedUpInboundGroupSessionEntities.size, machine.roomKeyCounts().backedUp.toInt())
|
assertEquals(backedUpInboundGroupSessionEntities.size, machine.roomKeyCounts().backedUp.toInt())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Test
|
// @Test
|
||||||
|
|
|
@ -20,11 +20,11 @@ import io.realm.RealmConfiguration
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
class MigrateEAtoEROperation {
|
class MigrateEAtoEROperation(private val migrateGroupSessions: Boolean = false) {
|
||||||
|
|
||||||
fun execute(cryptoRealm: RealmConfiguration, sessionFilesDir: File, passphrase: String?): File {
|
fun execute(cryptoRealm: RealmConfiguration, sessionFilesDir: File, passphrase: String?): File {
|
||||||
// to remove unused warning
|
// to remove unused warning
|
||||||
Timber.v("Not used in kotlin crypto $cryptoRealm ${"*".repeat(passphrase?.length ?: 0)}")
|
Timber.v("Not used in kotlin crypto $cryptoRealm ${"*".repeat(passphrase?.length ?: 0)} lazy:$migrateGroupSessions")
|
||||||
// no op in kotlinCrypto
|
// no op in kotlinCrypto
|
||||||
return sessionFilesDir
|
return sessionFilesDir
|
||||||
}
|
}
|
||||||
|
|
|
@ -82,6 +82,7 @@ import org.matrix.rustcomponents.sdk.crypto.RequestType
|
||||||
import org.matrix.rustcomponents.sdk.crypto.RoomKeyCounts
|
import org.matrix.rustcomponents.sdk.crypto.RoomKeyCounts
|
||||||
import org.matrix.rustcomponents.sdk.crypto.ShieldColor
|
import org.matrix.rustcomponents.sdk.crypto.ShieldColor
|
||||||
import org.matrix.rustcomponents.sdk.crypto.ShieldState
|
import org.matrix.rustcomponents.sdk.crypto.ShieldState
|
||||||
|
import org.matrix.rustcomponents.sdk.crypto.SignatureVerification
|
||||||
import org.matrix.rustcomponents.sdk.crypto.setLogger
|
import org.matrix.rustcomponents.sdk.crypto.setLogger
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
@ -916,7 +917,7 @@ internal class OlmMachine @Inject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
@Throws(CryptoStoreException::class)
|
@Throws(CryptoStoreException::class)
|
||||||
suspend fun checkAuthDataSignature(authData: KeysAlgorithmAndData): Boolean {
|
suspend fun checkAuthDataSignature(authData: KeysAlgorithmAndData): SignatureVerification {
|
||||||
return withContext(coroutineDispatchers.computation) {
|
return withContext(coroutineDispatchers.computation) {
|
||||||
val adapter = moshi
|
val adapter = moshi
|
||||||
.newBuilder()
|
.newBuilder()
|
||||||
|
@ -929,7 +930,7 @@ internal class OlmMachine @Inject constructor(
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
inner.verifyBackup(serializedAuthData).trusted
|
inner.verifyBackup(serializedAuthData)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,10 +28,13 @@ import org.matrix.android.sdk.api.session.crypto.crosssigning.isVerified
|
||||||
import org.matrix.android.sdk.api.session.crypto.model.CryptoDeviceInfo
|
import org.matrix.android.sdk.api.session.crypto.model.CryptoDeviceInfo
|
||||||
import org.matrix.android.sdk.api.session.crypto.model.RoomEncryptionTrustLevel
|
import org.matrix.android.sdk.api.session.crypto.model.RoomEncryptionTrustLevel
|
||||||
import org.matrix.android.sdk.api.util.Optional
|
import org.matrix.android.sdk.api.util.Optional
|
||||||
|
import org.matrix.android.sdk.internal.crypto.network.OutgoingRequestsProcessor
|
||||||
|
import org.matrix.rustcomponents.sdk.crypto.Request
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
internal class RustCrossSigningService @Inject constructor(
|
internal class RustCrossSigningService @Inject constructor(
|
||||||
private val olmMachine: OlmMachine,
|
private val olmMachine: OlmMachine,
|
||||||
|
private val outgoingRequestsProcessor: OutgoingRequestsProcessor,
|
||||||
private val computeShieldForGroup: ComputeShieldForGroupUseCase
|
private val computeShieldForGroup: ComputeShieldForGroupUseCase
|
||||||
) : CrossSigningService {
|
) : CrossSigningService {
|
||||||
|
|
||||||
|
@ -78,6 +81,10 @@ internal class RustCrossSigningService @Inject constructor(
|
||||||
* Users needs to enter credentials
|
* Users needs to enter credentials
|
||||||
*/
|
*/
|
||||||
override suspend fun initializeCrossSigning(uiaInterceptor: UserInteractiveAuthInterceptor?) {
|
override suspend fun initializeCrossSigning(uiaInterceptor: UserInteractiveAuthInterceptor?) {
|
||||||
|
// ensure our keys are sent before initialising
|
||||||
|
outgoingRequestsProcessor.processOutgoingRequests(olmMachine) {
|
||||||
|
it is Request.KeysUpload
|
||||||
|
}
|
||||||
olmMachine.bootstrapCrossSigning(uiaInterceptor)
|
olmMachine.bootstrapCrossSigning(uiaInterceptor)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -43,6 +43,7 @@ import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysBackupService
|
||||||
import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysBackupState
|
import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysBackupState
|
||||||
import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysBackupStateListener
|
import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysBackupStateListener
|
||||||
import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysBackupVersionTrust
|
import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysBackupVersionTrust
|
||||||
|
import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysBackupVersionTrustSignature
|
||||||
import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysVersion
|
import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysVersion
|
||||||
import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysVersionResult
|
import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysVersionResult
|
||||||
import org.matrix.android.sdk.api.session.crypto.keysbackup.MegolmBackupAuthData
|
import org.matrix.android.sdk.api.session.crypto.keysbackup.MegolmBackupAuthData
|
||||||
|
@ -67,6 +68,8 @@ import org.matrix.android.sdk.internal.util.JsonCanonicalizer
|
||||||
import org.matrix.olm.OlmException
|
import org.matrix.olm.OlmException
|
||||||
import org.matrix.rustcomponents.sdk.crypto.Request
|
import org.matrix.rustcomponents.sdk.crypto.Request
|
||||||
import org.matrix.rustcomponents.sdk.crypto.RequestType
|
import org.matrix.rustcomponents.sdk.crypto.RequestType
|
||||||
|
import org.matrix.rustcomponents.sdk.crypto.SignatureState
|
||||||
|
import org.matrix.rustcomponents.sdk.crypto.SignatureVerification
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import java.security.InvalidParameterException
|
import java.security.InvalidParameterException
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
@ -266,14 +269,56 @@ internal class RustKeyBackupService @Inject constructor(
|
||||||
private suspend fun checkBackupTrust(algAndData: KeysAlgorithmAndData?): KeysBackupVersionTrust {
|
private suspend fun checkBackupTrust(algAndData: KeysAlgorithmAndData?): KeysBackupVersionTrust {
|
||||||
if (algAndData == null) return KeysBackupVersionTrust(usable = false)
|
if (algAndData == null) return KeysBackupVersionTrust(usable = false)
|
||||||
try {
|
try {
|
||||||
val isTrusted = olmMachine.checkAuthDataSignature(algAndData)
|
val authData = olmMachine.checkAuthDataSignature(algAndData)
|
||||||
return KeysBackupVersionTrust(isTrusted)
|
val signatures = authData.mapRustToAPI()
|
||||||
|
return KeysBackupVersionTrust(authData.trusted, signatures)
|
||||||
} catch (failure: Throwable) {
|
} catch (failure: Throwable) {
|
||||||
Timber.w(failure, "Failed to trust backup")
|
Timber.w(failure, "Failed to trust backup")
|
||||||
return KeysBackupVersionTrust(usable = false)
|
return KeysBackupVersionTrust(usable = false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private suspend fun SignatureVerification.mapRustToAPI(): List<KeysBackupVersionTrustSignature> {
|
||||||
|
val signatures = mutableListOf<KeysBackupVersionTrustSignature>()
|
||||||
|
// signature state of own device
|
||||||
|
val ownDeviceState = this.deviceSignature
|
||||||
|
if (ownDeviceState != SignatureState.MISSING && ownDeviceState != SignatureState.INVALID) {
|
||||||
|
// we can add it
|
||||||
|
signatures.add(
|
||||||
|
KeysBackupVersionTrustSignature.DeviceSignature(
|
||||||
|
olmMachine.deviceId(),
|
||||||
|
olmMachine.getCryptoDeviceInfo(olmMachine.userId(), olmMachine.deviceId()),
|
||||||
|
ownDeviceState == SignatureState.VALID_AND_TRUSTED
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
// signature state of our own identity
|
||||||
|
val ownIdentityState = this.userIdentitySignature
|
||||||
|
if (ownIdentityState != SignatureState.MISSING && ownIdentityState != SignatureState.INVALID) {
|
||||||
|
// we can add it
|
||||||
|
val masterKey = olmMachine.getIdentity(olmMachine.userId())?.toMxCrossSigningInfo()?.masterKey()
|
||||||
|
signatures.add(
|
||||||
|
KeysBackupVersionTrustSignature.UserSignature(
|
||||||
|
masterKey?.unpaddedBase64PublicKey,
|
||||||
|
masterKey,
|
||||||
|
ownIdentityState == SignatureState.VALID_AND_TRUSTED
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
signatures.addAll(
|
||||||
|
this.otherDevicesSignatures
|
||||||
|
.filter { it.value == SignatureState.VALID_AND_TRUSTED || it.value == SignatureState.VALID_BUT_NOT_TRUSTED }
|
||||||
|
.map {
|
||||||
|
KeysBackupVersionTrustSignature.DeviceSignature(
|
||||||
|
it.key,
|
||||||
|
olmMachine.getCryptoDeviceInfo(olmMachine.userId(), it.key),
|
||||||
|
ownDeviceState == SignatureState.VALID_AND_TRUSTED
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
return signatures
|
||||||
|
}
|
||||||
|
|
||||||
override suspend fun getKeysBackupTrust(keysBackupVersion: KeysVersionResult): KeysBackupVersionTrust {
|
override suspend fun getKeysBackupTrust(keysBackupVersion: KeysVersionResult): KeysBackupVersionTrust {
|
||||||
return withContext(coroutineDispatchers.crypto) {
|
return withContext(coroutineDispatchers.crypto) {
|
||||||
checkBackupTrust(keysBackupVersion)
|
checkBackupTrust(keysBackupVersion)
|
||||||
|
@ -341,7 +386,7 @@ internal class RustKeyBackupService @Inject constructor(
|
||||||
val authData = getMegolmBackupAuthData(keysBackupData)
|
val authData = getMegolmBackupAuthData(keysBackupData)
|
||||||
|
|
||||||
when {
|
when {
|
||||||
authData == null -> {
|
authData == null -> {
|
||||||
Timber.w("isValidRecoveryKeyForKeysBackupVersion: Key backup is missing required data")
|
Timber.w("isValidRecoveryKeyForKeysBackupVersion: Key backup is missing required data")
|
||||||
throw IllegalArgumentException("Missing element")
|
throw IllegalArgumentException("Missing element")
|
||||||
}
|
}
|
||||||
|
@ -349,7 +394,7 @@ internal class RustKeyBackupService @Inject constructor(
|
||||||
Timber.w("isValidRecoveryKeyForKeysBackupVersion: Public keys mismatch")
|
Timber.w("isValidRecoveryKeyForKeysBackupVersion: Public keys mismatch")
|
||||||
throw IllegalArgumentException("Invalid recovery key or password")
|
throw IllegalArgumentException("Invalid recovery key or password")
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
// This case is fine, the public key on the server matches the public key the
|
// This case is fine, the public key on the server matches the public key the
|
||||||
// recovery key produced.
|
// recovery key produced.
|
||||||
}
|
}
|
||||||
|
@ -428,10 +473,10 @@ internal class RustKeyBackupService @Inject constructor(
|
||||||
roomId != null && sessionId != null -> {
|
roomId != null && sessionId != null -> {
|
||||||
sender.downloadBackedUpKeys(version, roomId, sessionId)
|
sender.downloadBackedUpKeys(version, roomId, sessionId)
|
||||||
}
|
}
|
||||||
roomId != null -> {
|
roomId != null -> {
|
||||||
sender.downloadBackedUpKeys(version, roomId)
|
sender.downloadBackedUpKeys(version, roomId)
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
sender.downloadBackedUpKeys(version)
|
sender.downloadBackedUpKeys(version)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -570,20 +615,24 @@ internal class RustKeyBackupService @Inject constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun restoreKeysWithRecoveryKey(keysVersionResult: KeysVersionResult,
|
override suspend fun restoreKeysWithRecoveryKey(
|
||||||
recoveryKey: IBackupRecoveryKey,
|
keysVersionResult: KeysVersionResult,
|
||||||
roomId: String?,
|
recoveryKey: IBackupRecoveryKey,
|
||||||
sessionId: String?,
|
roomId: String?,
|
||||||
stepProgressListener: StepProgressListener?): ImportRoomKeysResult {
|
sessionId: String?,
|
||||||
|
stepProgressListener: StepProgressListener?
|
||||||
|
): ImportRoomKeysResult {
|
||||||
Timber.v("restoreKeysWithRecoveryKey: From backup version: ${keysVersionResult.version}")
|
Timber.v("restoreKeysWithRecoveryKey: From backup version: ${keysVersionResult.version}")
|
||||||
return restoreBackup(keysVersionResult, recoveryKey, roomId, sessionId, stepProgressListener)
|
return restoreBackup(keysVersionResult, recoveryKey, roomId, sessionId, stepProgressListener)
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun restoreKeyBackupWithPassword(keysBackupVersion: KeysVersionResult,
|
override suspend fun restoreKeyBackupWithPassword(
|
||||||
password: String,
|
keysBackupVersion: KeysVersionResult,
|
||||||
roomId: String?,
|
password: String,
|
||||||
sessionId: String?,
|
roomId: String?,
|
||||||
stepProgressListener: StepProgressListener?): ImportRoomKeysResult {
|
sessionId: String?,
|
||||||
|
stepProgressListener: StepProgressListener?
|
||||||
|
): ImportRoomKeysResult {
|
||||||
Timber.v("[MXKeyBackup] restoreKeyBackup with password: From backup version: ${keysBackupVersion.version}")
|
Timber.v("[MXKeyBackup] restoreKeyBackup with password: From backup version: ${keysBackupVersion.version}")
|
||||||
val recoveryKey = withContext(coroutineDispatchers.crypto) {
|
val recoveryKey = withContext(coroutineDispatchers.crypto) {
|
||||||
recoveryKeyFromPassword(password, keysBackupVersion)
|
recoveryKeyFromPassword(password, keysBackupVersion)
|
||||||
|
@ -752,13 +801,13 @@ internal class RustKeyBackupService @Inject constructor(
|
||||||
val authData = getMegolmBackupAuthData(keysBackupData)
|
val authData = getMegolmBackupAuthData(keysBackupData)
|
||||||
|
|
||||||
return when {
|
return when {
|
||||||
authData == null -> {
|
authData == null -> {
|
||||||
throw IllegalArgumentException("recoveryKeyFromPassword: invalid parameter")
|
throw IllegalArgumentException("recoveryKeyFromPassword: invalid parameter")
|
||||||
}
|
}
|
||||||
authData.privateKeySalt.isNullOrBlank() || authData.privateKeyIterations == null -> {
|
authData.privateKeySalt.isNullOrBlank() || authData.privateKeyIterations == null -> {
|
||||||
throw java.lang.IllegalArgumentException("recoveryKeyFromPassword: Salt and/or iterations not found in key backup auth data")
|
throw java.lang.IllegalArgumentException("recoveryKeyFromPassword: Salt and/or iterations not found in key backup auth data")
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
BackupRecoveryKey.fromPassphrase(password, authData.privateKeySalt, authData.privateKeyIterations)
|
BackupRecoveryKey.fromPassphrase(password, authData.privateKeySalt, authData.privateKeyIterations)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -811,7 +860,7 @@ internal class RustKeyBackupService @Inject constructor(
|
||||||
suspend fun maybeBackupKeys() {
|
suspend fun maybeBackupKeys() {
|
||||||
withContext(coroutineDispatchers.crypto) {
|
withContext(coroutineDispatchers.crypto) {
|
||||||
when {
|
when {
|
||||||
isStuck() -> {
|
isStuck() -> {
|
||||||
// If not already done, or in error case, check for a valid backup version on the homeserver.
|
// If not already done, or in error case, check for a valid backup version on the homeserver.
|
||||||
// If there is one, maybeBackupKeys will be called again.
|
// If there is one, maybeBackupKeys will be called again.
|
||||||
checkAndStartKeysBackup()
|
checkAndStartKeysBackup()
|
||||||
|
@ -829,7 +878,7 @@ internal class RustKeyBackupService @Inject constructor(
|
||||||
tryOrNull("AUTO backup failed") { backupKeys() }
|
tryOrNull("AUTO backup failed") { backupKeys() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
Timber.v("maybeBackupKeys: Skip it because state: ${getState()}")
|
Timber.v("maybeBackupKeys: Skip it because state: ${getState()}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -907,7 +956,7 @@ internal class RustKeyBackupService @Inject constructor(
|
||||||
// is available on the homeserver
|
// is available on the homeserver
|
||||||
checkAndStartKeysBackup()
|
checkAndStartKeysBackup()
|
||||||
}
|
}
|
||||||
else ->
|
else ->
|
||||||
// Come back to the ready state so that we will retry on the next received key
|
// Come back to the ready state so that we will retry on the next received key
|
||||||
keysBackupStateManager.state = KeysBackupState.ReadyToBackUp
|
keysBackupStateManager.state = KeysBackupState.ReadyToBackUp
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,7 +38,7 @@ import kotlin.system.measureTimeMillis
|
||||||
|
|
||||||
private val charset = Charset.forName("UTF-8")
|
private val charset = Charset.forName("UTF-8")
|
||||||
|
|
||||||
internal class ExtractMigrationDataUseCase {
|
internal class ExtractMigrationDataUseCase(val migrateGroupSessions: Boolean = false) {
|
||||||
|
|
||||||
fun extractData(realm: Realm, importPartial: ((MigrationData) -> Unit)) {
|
fun extractData(realm: Realm, importPartial: ((MigrationData) -> Unit)) {
|
||||||
return try {
|
return try {
|
||||||
|
@ -143,35 +143,37 @@ internal class ExtractMigrationDataUseCase {
|
||||||
Timber.i("Migration: rust import time $writeTime")
|
Timber.i("Migration: rust import time $writeTime")
|
||||||
}
|
}
|
||||||
|
|
||||||
// We don't migrate outbound session directly after migration
|
// We don't migrate outbound session by default directly after migration
|
||||||
// We are going to do it lazyly when decryption fails
|
// We are going to do it lazyly when decryption fails
|
||||||
// var migratedInboundGroupSessionCount = 0
|
if (migrateGroupSessions) {
|
||||||
// readTime = 0
|
var migratedInboundGroupSessionCount = 0
|
||||||
// writeTime = 0
|
readTime = 0
|
||||||
// measureTimeMillis {
|
writeTime = 0
|
||||||
// realm.where<OlmInboundGroupSessionEntity>()
|
measureTimeMillis {
|
||||||
// .findAll()
|
realm.where<OlmInboundGroupSessionEntity>()
|
||||||
// .chunked(chunkSize) { chunk ->
|
.findAll()
|
||||||
// val export: List<PickledInboundGroupSession>
|
.chunked(chunkSize) { chunk ->
|
||||||
// measureTimeMillis {
|
val export: List<PickledInboundGroupSession>
|
||||||
// export = chunk.mapNotNull { it.toPickledInboundGroupSession(pickleKey) }
|
measureTimeMillis {
|
||||||
// }.also {
|
export = chunk.mapNotNull { it.toPickledInboundGroupSession(pickleKey) }
|
||||||
// readTime += it
|
}.also {
|
||||||
// }
|
readTime += it
|
||||||
// migratedInboundGroupSessionCount+=export.size
|
}
|
||||||
// measureTimeMillis {
|
migratedInboundGroupSessionCount += export.size
|
||||||
// importPartial(
|
measureTimeMillis {
|
||||||
// baseExtract.copy(inboundGroupSessions = export)
|
importPartial(
|
||||||
// )
|
baseExtract.copy(inboundGroupSessions = export)
|
||||||
// }.also {
|
)
|
||||||
// writeTime += it
|
}.also {
|
||||||
// }
|
writeTime += it
|
||||||
// }
|
}
|
||||||
// }.also {
|
}
|
||||||
// Timber.i("Migration: took $it ms to migrate $migratedInboundGroupSessionCount group sessions")
|
}.also {
|
||||||
// Timber.i("Migration: extract time $readTime")
|
Timber.i("Migration: took $it ms to migrate $migratedInboundGroupSessionCount group sessions")
|
||||||
// Timber.i("Migration: rust import time $writeTime")
|
Timber.i("Migration: extract time $readTime")
|
||||||
// }
|
Timber.i("Migration: rust import time $writeTime")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// return baseExtract
|
// return baseExtract
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,14 +23,14 @@ import org.matrix.rustcomponents.sdk.crypto.ProgressListener
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
class MigrateEAtoEROperation {
|
class MigrateEAtoEROperation(private val migrateGroupSessions: Boolean = false) {
|
||||||
|
|
||||||
fun execute(cryptoRealm: RealmConfiguration, rustFilesDir: File, passphrase: String?): File {
|
fun execute(cryptoRealm: RealmConfiguration, rustFilesDir: File, passphrase: String?): File {
|
||||||
// Temporary code for migration
|
// Temporary code for migration
|
||||||
if (!rustFilesDir.exists()) {
|
if (!rustFilesDir.exists()) {
|
||||||
rustFilesDir.mkdir()
|
rustFilesDir.mkdir()
|
||||||
// perform a migration?
|
// perform a migration?
|
||||||
val extractMigrationData = ExtractMigrationDataUseCase()
|
val extractMigrationData = ExtractMigrationDataUseCase(migrateGroupSessions)
|
||||||
val hasExitingData = extractMigrationData.hasExistingData(cryptoRealm)
|
val hasExitingData = extractMigrationData.hasExistingData(cryptoRealm)
|
||||||
if (!hasExitingData) return rustFilesDir
|
if (!hasExitingData) return rustFilesDir
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue