Merge branch 'release/1.6.0' into develop
This commit is contained in:
commit
218b5c0b77
38
Gemfile.lock
38
Gemfile.lock
@ -9,17 +9,17 @@ GEM
|
|||||||
artifactory (3.0.15)
|
artifactory (3.0.15)
|
||||||
atomos (0.1.3)
|
atomos (0.1.3)
|
||||||
aws-eventstream (1.1.1)
|
aws-eventstream (1.1.1)
|
||||||
aws-partitions (1.479.0)
|
aws-partitions (1.490.0)
|
||||||
aws-sdk-core (3.117.0)
|
aws-sdk-core (3.119.1)
|
||||||
aws-eventstream (~> 1, >= 1.0.2)
|
aws-eventstream (~> 1, >= 1.0.2)
|
||||||
aws-partitions (~> 1, >= 1.239.0)
|
aws-partitions (~> 1, >= 1.239.0)
|
||||||
aws-sigv4 (~> 1.1)
|
aws-sigv4 (~> 1.1)
|
||||||
jmespath (~> 1.0)
|
jmespath (~> 1.0)
|
||||||
aws-sdk-kms (1.44.0)
|
aws-sdk-kms (1.46.0)
|
||||||
aws-sdk-core (~> 3, >= 3.112.0)
|
aws-sdk-core (~> 3, >= 3.119.0)
|
||||||
aws-sigv4 (~> 1.1)
|
aws-sigv4 (~> 1.1)
|
||||||
aws-sdk-s3 (1.96.2)
|
aws-sdk-s3 (1.99.0)
|
||||||
aws-sdk-core (~> 3, >= 3.112.0)
|
aws-sdk-core (~> 3, >= 3.119.0)
|
||||||
aws-sdk-kms (~> 1)
|
aws-sdk-kms (~> 1)
|
||||||
aws-sigv4 (~> 1.1)
|
aws-sigv4 (~> 1.1)
|
||||||
aws-sigv4 (1.2.4)
|
aws-sigv4 (1.2.4)
|
||||||
@ -40,7 +40,7 @@ GEM
|
|||||||
ed25519 (1.2.4)
|
ed25519 (1.2.4)
|
||||||
emoji_regex (3.2.2)
|
emoji_regex (3.2.2)
|
||||||
excon (0.85.0)
|
excon (0.85.0)
|
||||||
faraday (1.5.1)
|
faraday (1.7.0)
|
||||||
faraday-em_http (~> 1.0)
|
faraday-em_http (~> 1.0)
|
||||||
faraday-em_synchrony (~> 1.0)
|
faraday-em_synchrony (~> 1.0)
|
||||||
faraday-excon (~> 1.1)
|
faraday-excon (~> 1.1)
|
||||||
@ -48,6 +48,7 @@ GEM
|
|||||||
faraday-net_http (~> 1.0)
|
faraday-net_http (~> 1.0)
|
||||||
faraday-net_http_persistent (~> 1.1)
|
faraday-net_http_persistent (~> 1.1)
|
||||||
faraday-patron (~> 1.0)
|
faraday-patron (~> 1.0)
|
||||||
|
faraday-rack (~> 1.0)
|
||||||
multipart-post (>= 1.2, < 3)
|
multipart-post (>= 1.2, < 3)
|
||||||
ruby2_keywords (>= 0.0.4)
|
ruby2_keywords (>= 0.0.4)
|
||||||
faraday-cookie_jar (0.0.7)
|
faraday-cookie_jar (0.0.7)
|
||||||
@ -60,10 +61,11 @@ GEM
|
|||||||
faraday-net_http (1.0.1)
|
faraday-net_http (1.0.1)
|
||||||
faraday-net_http_persistent (1.2.0)
|
faraday-net_http_persistent (1.2.0)
|
||||||
faraday-patron (1.0.0)
|
faraday-patron (1.0.0)
|
||||||
faraday_middleware (1.0.0)
|
faraday-rack (1.0.0)
|
||||||
|
faraday_middleware (1.1.0)
|
||||||
faraday (~> 1.0)
|
faraday (~> 1.0)
|
||||||
fastimage (2.2.4)
|
fastimage (2.2.5)
|
||||||
fastlane (2.188.0)
|
fastlane (2.192.0)
|
||||||
CFPropertyList (>= 2.3, < 4.0.0)
|
CFPropertyList (>= 2.3, < 4.0.0)
|
||||||
addressable (>= 2.8, < 3.0.0)
|
addressable (>= 2.8, < 3.0.0)
|
||||||
artifactory (~> 3.0)
|
artifactory (~> 3.0)
|
||||||
@ -80,7 +82,7 @@ GEM
|
|||||||
faraday_middleware (~> 1.0)
|
faraday_middleware (~> 1.0)
|
||||||
fastimage (>= 2.1.0, < 3.0.0)
|
fastimage (>= 2.1.0, < 3.0.0)
|
||||||
gh_inspector (>= 1.1.2, < 2.0.0)
|
gh_inspector (>= 1.1.2, < 2.0.0)
|
||||||
google-apis-androidpublisher_v3 (~> 0.1)
|
google-apis-androidpublisher_v3 (~> 0.3)
|
||||||
google-apis-playcustomapp_v1 (~> 0.1)
|
google-apis-playcustomapp_v1 (~> 0.1)
|
||||||
google-cloud-storage (~> 1.31)
|
google-cloud-storage (~> 1.31)
|
||||||
highline (~> 2.0)
|
highline (~> 2.0)
|
||||||
@ -89,6 +91,7 @@ GEM
|
|||||||
mini_magick (>= 4.9.4, < 5.0.0)
|
mini_magick (>= 4.9.4, < 5.0.0)
|
||||||
multipart-post (~> 2.0.0)
|
multipart-post (~> 2.0.0)
|
||||||
naturally (~> 2.2)
|
naturally (~> 2.2)
|
||||||
|
optparse (~> 0.1.1)
|
||||||
plist (>= 3.1.0, < 4.0.0)
|
plist (>= 3.1.0, < 4.0.0)
|
||||||
rubyzip (>= 2.0.0, < 3.0.0)
|
rubyzip (>= 2.0.0, < 3.0.0)
|
||||||
security (= 0.1.3)
|
security (= 0.1.3)
|
||||||
@ -101,13 +104,13 @@ GEM
|
|||||||
xcodeproj (>= 1.13.0, < 2.0.0)
|
xcodeproj (>= 1.13.0, < 2.0.0)
|
||||||
xcpretty (~> 0.3.0)
|
xcpretty (~> 0.3.0)
|
||||||
xcpretty-travis-formatter (>= 0.0.3)
|
xcpretty-travis-formatter (>= 0.0.3)
|
||||||
fastlane-plugin-aws_s3 (2.0.2)
|
fastlane-plugin-aws_s3 (2.0.3)
|
||||||
apktools (~> 0.7)
|
apktools (~> 0.7)
|
||||||
aws-sdk-s3 (~> 1)
|
aws-sdk-s3 (~> 1)
|
||||||
mime-types (~> 3.3)
|
mime-types (~> 3.3)
|
||||||
fastlane-plugin-get_version_name (0.2.2)
|
fastlane-plugin-get_version_name (0.2.2)
|
||||||
gh_inspector (1.1.3)
|
gh_inspector (1.1.3)
|
||||||
google-apis-androidpublisher_v3 (0.9.0)
|
google-apis-androidpublisher_v3 (0.10.0)
|
||||||
google-apis-core (>= 0.4, < 2.a)
|
google-apis-core (>= 0.4, < 2.a)
|
||||||
google-apis-core (0.4.1)
|
google-apis-core (0.4.1)
|
||||||
addressable (~> 2.5, >= 2.5.1)
|
addressable (~> 2.5, >= 2.5.1)
|
||||||
@ -118,7 +121,7 @@ GEM
|
|||||||
retriable (>= 2.0, < 4.a)
|
retriable (>= 2.0, < 4.a)
|
||||||
rexml
|
rexml
|
||||||
webrick
|
webrick
|
||||||
google-apis-iamcredentials_v1 (0.6.0)
|
google-apis-iamcredentials_v1 (0.7.0)
|
||||||
google-apis-core (>= 0.4, < 2.a)
|
google-apis-core (>= 0.4, < 2.a)
|
||||||
google-apis-playcustomapp_v1 (0.5.0)
|
google-apis-playcustomapp_v1 (0.5.0)
|
||||||
google-apis-core (>= 0.4, < 2.a)
|
google-apis-core (>= 0.4, < 2.a)
|
||||||
@ -138,7 +141,7 @@ GEM
|
|||||||
google-cloud-core (~> 1.6)
|
google-cloud-core (~> 1.6)
|
||||||
googleauth (>= 0.16.2, < 2.a)
|
googleauth (>= 0.16.2, < 2.a)
|
||||||
mini_mime (~> 1.0)
|
mini_mime (~> 1.0)
|
||||||
googleauth (0.16.2)
|
googleauth (0.17.0)
|
||||||
faraday (>= 0.17.3, < 2.0)
|
faraday (>= 0.17.3, < 2.0)
|
||||||
jwt (>= 1.4, < 3.0)
|
jwt (>= 1.4, < 3.0)
|
||||||
memoist (~> 0.16)
|
memoist (~> 0.16)
|
||||||
@ -157,7 +160,7 @@ GEM
|
|||||||
mime-types-data (~> 3.2015)
|
mime-types-data (~> 3.2015)
|
||||||
mime-types-data (3.2021.0704)
|
mime-types-data (3.2021.0704)
|
||||||
mini_magick (4.11.0)
|
mini_magick (4.11.0)
|
||||||
mini_mime (1.1.0)
|
mini_mime (1.1.1)
|
||||||
multi_json (1.15.0)
|
multi_json (1.15.0)
|
||||||
multipart-post (2.0.0)
|
multipart-post (2.0.0)
|
||||||
nanaimo (0.3.0)
|
nanaimo (0.3.0)
|
||||||
@ -165,6 +168,7 @@ GEM
|
|||||||
net-sftp (3.0.0)
|
net-sftp (3.0.0)
|
||||||
net-ssh (>= 5.0.0, < 7.0.0)
|
net-ssh (>= 5.0.0, < 7.0.0)
|
||||||
net-ssh (6.1.0)
|
net-ssh (6.1.0)
|
||||||
|
optparse (0.1.1)
|
||||||
os (1.1.1)
|
os (1.1.1)
|
||||||
plist (3.6.0)
|
plist (3.6.0)
|
||||||
public_suffix (4.0.6)
|
public_suffix (4.0.6)
|
||||||
@ -202,7 +206,7 @@ GEM
|
|||||||
unicode-display_width (1.7.0)
|
unicode-display_width (1.7.0)
|
||||||
webrick (1.7.0)
|
webrick (1.7.0)
|
||||||
word_wrap (1.0.0)
|
word_wrap (1.0.0)
|
||||||
xcodeproj (1.20.0)
|
xcodeproj (1.21.0)
|
||||||
CFPropertyList (>= 2.3.3, < 4.0)
|
CFPropertyList (>= 2.3.3, < 4.0)
|
||||||
atomos (~> 0.1.3)
|
atomos (~> 0.1.3)
|
||||||
claide (>= 1.0.2, < 2.0)
|
claide (>= 1.0.2, < 2.0)
|
||||||
|
@ -2,7 +2,7 @@ apply from: 'buildsystem/dependencies.gradle'
|
|||||||
apply plugin: "com.vanniktech.android.junit.jacoco"
|
apply plugin: "com.vanniktech.android.junit.jacoco"
|
||||||
|
|
||||||
buildscript {
|
buildscript {
|
||||||
ext.kotlin_version = '1.5.21'
|
ext.kotlin_version = '1.5.30'
|
||||||
repositories {
|
repositories {
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
google()
|
google()
|
||||||
@ -39,7 +39,7 @@ allprojects {
|
|||||||
ext {
|
ext {
|
||||||
androidApplicationId = 'org.cryptomator'
|
androidApplicationId = 'org.cryptomator'
|
||||||
androidVersionCode = getVersionCode()
|
androidVersionCode = getVersionCode()
|
||||||
androidVersionName = '1.6.1-SNAPSHOT'
|
androidVersionName = '1.6.0-SNAPSHOT'
|
||||||
}
|
}
|
||||||
repositories {
|
repositories {
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
|
@ -29,16 +29,16 @@ ext {
|
|||||||
rxAndroidVersion = '2.1.1'
|
rxAndroidVersion = '2.1.1'
|
||||||
rxBindingVersion = '2.2.0'
|
rxBindingVersion = '2.2.0'
|
||||||
|
|
||||||
daggerVersion = '2.37'
|
daggerVersion = '2.38.1'
|
||||||
|
|
||||||
gsonVersion = '2.8.7'
|
gsonVersion = '2.8.8'
|
||||||
|
|
||||||
okHttpVersion = '4.9.1'
|
okHttpVersion = '4.9.1'
|
||||||
okHttpDigestVersion = '2.5'
|
okHttpDigestVersion = '2.5'
|
||||||
|
|
||||||
velocityVersion = '2.3'
|
velocityVersion = '2.3'
|
||||||
|
|
||||||
timberVersion = '4.7.1'
|
timberVersion = '5.0.1'
|
||||||
|
|
||||||
zxcvbnVersion = '1.5.2'
|
zxcvbnVersion = '1.5.2'
|
||||||
|
|
||||||
@ -50,17 +50,17 @@ ext {
|
|||||||
greenDaoVersion = '3.3.0'
|
greenDaoVersion = '3.3.0'
|
||||||
|
|
||||||
// cloud provider libs
|
// cloud provider libs
|
||||||
cryptolibVersion = '2.0.0-rc6'
|
cryptolibVersion = '2.0.2'
|
||||||
|
|
||||||
dropboxVersion = '4.0.0'
|
dropboxVersion = '4.0.0'
|
||||||
|
|
||||||
googleApiServicesVersion = 'v3-rev197-1.25.0'
|
googleApiServicesVersion = 'v3-rev20210725-1.32.1'
|
||||||
googlePlayServicesVersion = '19.0.0'
|
googlePlayServicesVersion = '19.0.0'
|
||||||
googleClientVersion = '1.32.1'
|
googleClientVersion = '1.32.1'
|
||||||
|
|
||||||
msgraphVersion = '2.10.0'
|
msgraphVersion = '2.10.0'
|
||||||
|
|
||||||
minIoVersion = '8.2.2'
|
minIoVersion = '8.3.0'
|
||||||
staxVersion = '1.2.0' // needed for minIO
|
staxVersion = '1.2.0' // needed for minIO
|
||||||
|
|
||||||
commonsCodecVersion = '1.15'
|
commonsCodecVersion = '1.15'
|
||||||
@ -72,7 +72,7 @@ ext {
|
|||||||
jUnitVersion = '5.7.1'
|
jUnitVersion = '5.7.1'
|
||||||
jUnit4Version = '4.13.1'
|
jUnit4Version = '4.13.1'
|
||||||
assertJVersion = '1.7.1'
|
assertJVersion = '1.7.1'
|
||||||
mockitoVersion = '3.11.2'
|
mockitoVersion = '3.12.1'
|
||||||
mockitoKotlinVersion = '3.2.0'
|
mockitoKotlinVersion = '3.2.0'
|
||||||
hamcrestVersion = '1.3'
|
hamcrestVersion = '1.3'
|
||||||
dexmakerVersion = '1.0'
|
dexmakerVersion = '1.0'
|
||||||
|
@ -75,6 +75,10 @@ android {
|
|||||||
java.srcDirs = ['src/main/java', 'src/main/java/', 'src/foss/java', 'src/foss/java/']
|
java.srcDirs = ['src/main/java', 'src/main/java/', 'src/foss/java', 'src/foss/java/']
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
packagingOptions {
|
||||||
|
exclude 'META-INF/DEPENDENCIES'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
greendao {
|
greendao {
|
||||||
@ -167,6 +171,10 @@ dependencies {
|
|||||||
testImplementation dependencies.mockitoKotlin
|
testImplementation dependencies.mockitoKotlin
|
||||||
testImplementation dependencies.mockitoInline
|
testImplementation dependencies.mockitoInline
|
||||||
testImplementation dependencies.hamcrest
|
testImplementation dependencies.hamcrest
|
||||||
|
|
||||||
|
androidTestImplementation(dependencies.runner) {
|
||||||
|
exclude group: 'com.android.support', module: 'support-annotations'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
configurations {
|
configurations {
|
||||||
|
@ -0,0 +1,410 @@
|
|||||||
|
package org.cryptomator.data.db
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.database.sqlite.SQLiteDatabase
|
||||||
|
import androidx.test.InstrumentationRegistry
|
||||||
|
import androidx.test.filters.SmallTest
|
||||||
|
import androidx.test.runner.AndroidJUnit4
|
||||||
|
import org.cryptomator.data.db.entities.CloudEntityDao
|
||||||
|
import org.cryptomator.data.db.entities.UpdateCheckEntityDao
|
||||||
|
import org.cryptomator.data.db.entities.VaultEntityDao
|
||||||
|
import org.cryptomator.domain.CloudType
|
||||||
|
import org.cryptomator.util.SharedPreferencesHandler
|
||||||
|
import org.cryptomator.util.crypto.CredentialCryptor
|
||||||
|
import org.greenrobot.greendao.database.Database
|
||||||
|
import org.greenrobot.greendao.database.StandardDatabase
|
||||||
|
import org.greenrobot.greendao.internal.DaoConfig
|
||||||
|
import org.hamcrest.CoreMatchers
|
||||||
|
import org.junit.After
|
||||||
|
import org.junit.Assert
|
||||||
|
import org.junit.Before
|
||||||
|
import org.junit.Test
|
||||||
|
import org.junit.runner.RunWith
|
||||||
|
|
||||||
|
@RunWith(AndroidJUnit4::class)
|
||||||
|
@SmallTest
|
||||||
|
class UpgradeDatabaseTest {
|
||||||
|
|
||||||
|
private val context = InstrumentationRegistry.getTargetContext()
|
||||||
|
private val sharedPreferencesHandler = SharedPreferencesHandler(context)
|
||||||
|
private lateinit var db: Database
|
||||||
|
|
||||||
|
@Before
|
||||||
|
fun setup() {
|
||||||
|
db = StandardDatabase(SQLiteDatabase.create(null))
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
fun tearDown() {
|
||||||
|
db.close()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun upgradeAll() {
|
||||||
|
Upgrade0To1().applyTo(db, 0)
|
||||||
|
Upgrade1To2().applyTo(db, 1)
|
||||||
|
Upgrade2To3(context).applyTo(db, 2)
|
||||||
|
Upgrade3To4().applyTo(db, 3)
|
||||||
|
Upgrade4To5().applyTo(db, 4)
|
||||||
|
Upgrade5To6().applyTo(db, 5)
|
||||||
|
Upgrade6To7().applyTo(db, 6)
|
||||||
|
Upgrade7To8().applyTo(db, 7)
|
||||||
|
Upgrade8To9(sharedPreferencesHandler).applyTo(db, 8)
|
||||||
|
|
||||||
|
CloudEntityDao(DaoConfig(db, CloudEntityDao::class.java)).loadAll()
|
||||||
|
VaultEntityDao(DaoConfig(db, VaultEntityDao::class.java)).loadAll()
|
||||||
|
UpdateCheckEntityDao(DaoConfig(db, UpdateCheckEntityDao::class.java)).loadAll()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun upgrade2To3() {
|
||||||
|
Upgrade0To1().applyTo(db, 0)
|
||||||
|
Upgrade1To2().applyTo(db, 1)
|
||||||
|
|
||||||
|
val url = "url"
|
||||||
|
val username = "username"
|
||||||
|
val webdavCertificate = "webdavCertificate"
|
||||||
|
val accessToken = "accessToken"
|
||||||
|
|
||||||
|
Sql.update("CLOUD_ENTITY")
|
||||||
|
.where("TYPE", Sql.eq("DROPBOX"))
|
||||||
|
.set("ACCESS_TOKEN", Sql.toString(accessToken))
|
||||||
|
.set("WEBDAV_URL", Sql.toString(url))
|
||||||
|
.set("USERNAME", Sql.toString(username))
|
||||||
|
.set("WEBDAV_CERTIFICATE", Sql.toString(webdavCertificate))
|
||||||
|
.executeOn(db)
|
||||||
|
|
||||||
|
Sql.update("CLOUD_ENTITY")
|
||||||
|
.where("TYPE", Sql.eq("ONEDRIVE"))
|
||||||
|
.set("ACCESS_TOKEN", Sql.toString("NOT USED"))
|
||||||
|
.set("WEBDAV_URL", Sql.toString(url))
|
||||||
|
.set("USERNAME", Sql.toString(username))
|
||||||
|
.set("WEBDAV_CERTIFICATE", Sql.toString(webdavCertificate))
|
||||||
|
.executeOn(db)
|
||||||
|
|
||||||
|
context.getSharedPreferences("com.microsoft.live", Context.MODE_PRIVATE).edit().putString("refresh_token", accessToken).commit()
|
||||||
|
|
||||||
|
Upgrade2To3(context).applyTo(db, 2)
|
||||||
|
|
||||||
|
checkUpgrade2to3ResultForCloud("DROPBOX", accessToken, url, username, webdavCertificate)
|
||||||
|
checkUpgrade2to3ResultForCloud("ONEDRIVE", accessToken, url, username, webdavCertificate)
|
||||||
|
|
||||||
|
Assert.assertThat(context.getSharedPreferences("com.microsoft.live", Context.MODE_PRIVATE).getString("refresh_token", null), CoreMatchers.nullValue())
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun checkUpgrade2to3ResultForCloud(cloudName: String, accessToken: String, url: String, username: String, webdavCertificate: String) {
|
||||||
|
Sql.query("CLOUD_ENTITY").where("TYPE", Sql.eq(cloudName)).executeOn(db).use {
|
||||||
|
it.moveToFirst()
|
||||||
|
Assert.assertThat(CredentialCryptor.getInstance(context).decrypt(it.getString(it.getColumnIndex("ACCESS_TOKEN"))), CoreMatchers.`is`(accessToken))
|
||||||
|
Assert.assertThat(it.getString(it.getColumnIndex("WEBDAV_URL")), CoreMatchers.`is`(url))
|
||||||
|
Assert.assertThat(it.getString(it.getColumnIndex("USERNAME")), CoreMatchers.`is`(username))
|
||||||
|
Assert.assertThat(it.getString(it.getColumnIndex("WEBDAV_CERTIFICATE")), CoreMatchers.`is`(webdavCertificate))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun upgrade3To4() {
|
||||||
|
Upgrade0To1().applyTo(db, 0)
|
||||||
|
Upgrade1To2().applyTo(db, 1)
|
||||||
|
Upgrade2To3(context).applyTo(db, 2)
|
||||||
|
|
||||||
|
val ids = arrayOf("10", "20", "31", "32", "51")
|
||||||
|
|
||||||
|
ids.forEach {
|
||||||
|
Sql.insertInto("VAULT_ENTITY") //
|
||||||
|
.integer("_id", Integer.parseInt(it)) //
|
||||||
|
.integer("FOLDER_CLOUD_ID", 1) //
|
||||||
|
.text("FOLDER_PATH", "path${it}") //
|
||||||
|
.text("FOLDER_NAME", "name${it}") //
|
||||||
|
.text("CLOUD_TYPE", CloudType.DROPBOX.name) //
|
||||||
|
.text("PASSWORD", "password${it}") //
|
||||||
|
.executeOn(db)
|
||||||
|
}
|
||||||
|
|
||||||
|
Upgrade3To4().applyTo(db, 3)
|
||||||
|
|
||||||
|
Sql.query("VAULT_ENTITY").where("CLOUD_TYPE", Sql.eq(CloudType.DROPBOX.name)).executeOn(db).use {
|
||||||
|
Assert.assertThat(it.count, CoreMatchers.`is`(ids.size))
|
||||||
|
while (it.moveToNext()) {
|
||||||
|
Assert.assertThat(it.getString(it.getColumnIndex("_id")), CoreMatchers.`is`(ids[it.position]))
|
||||||
|
Assert.assertThat(it.getInt(it.getColumnIndex("POSITION")), CoreMatchers.`is`(it.position))
|
||||||
|
Assert.assertThat(it.getInt(it.getColumnIndex("FOLDER_CLOUD_ID")), CoreMatchers.`is`(1))
|
||||||
|
Assert.assertThat(it.getString(it.getColumnIndex("FOLDER_PATH")), CoreMatchers.`is`("path${ids[it.position]}"))
|
||||||
|
Assert.assertThat(it.getString(it.getColumnIndex("FOLDER_NAME")), CoreMatchers.`is`("name${ids[it.position]}"))
|
||||||
|
Assert.assertThat(it.getString(it.getColumnIndex("CLOUD_TYPE")), CoreMatchers.`is`(CloudType.DROPBOX.name))
|
||||||
|
Assert.assertThat(it.getString(it.getColumnIndex("PASSWORD")), CoreMatchers.`is`("password${ids[it.position]}"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun upgrade4To5() {
|
||||||
|
Upgrade0To1().applyTo(db, 0)
|
||||||
|
Upgrade1To2().applyTo(db, 1)
|
||||||
|
Upgrade2To3(context).applyTo(db, 2)
|
||||||
|
Upgrade3To4().applyTo(db, 3)
|
||||||
|
|
||||||
|
val cloudId = 15
|
||||||
|
val cloudUrl = "url"
|
||||||
|
val username = "username"
|
||||||
|
val webdavCertificate = "webdavCertificate"
|
||||||
|
val accessToken = "accessToken"
|
||||||
|
|
||||||
|
val vaultId = 25
|
||||||
|
val folderPath = "path"
|
||||||
|
val folderName = "name"
|
||||||
|
val password = "password"
|
||||||
|
val position = 10
|
||||||
|
|
||||||
|
Sql.insertInto("CLOUD_ENTITY") //
|
||||||
|
.integer("_id", cloudId) //
|
||||||
|
.text("TYPE", CloudType.WEBDAV.name) //
|
||||||
|
.text("ACCESS_TOKEN", accessToken) //
|
||||||
|
.text("WEBDAV_URL", cloudUrl) //
|
||||||
|
.text("USERNAME", username) //
|
||||||
|
.text("WEBDAV_CERTIFICATE", webdavCertificate) //
|
||||||
|
.executeOn(db)
|
||||||
|
|
||||||
|
Sql.insertInto("VAULT_ENTITY") //
|
||||||
|
.integer("_id", vaultId) //
|
||||||
|
.integer("FOLDER_CLOUD_ID", cloudId) //
|
||||||
|
.text("FOLDER_PATH", folderPath) //
|
||||||
|
.text("FOLDER_NAME", folderName) //
|
||||||
|
.text("CLOUD_TYPE", CloudType.WEBDAV.name) //
|
||||||
|
.text("PASSWORD", password) //
|
||||||
|
.integer("POSITION", position) //
|
||||||
|
.executeOn(db)
|
||||||
|
|
||||||
|
Upgrade4To5().applyTo(db, 4)
|
||||||
|
|
||||||
|
Sql.query("CLOUD_ENTITY").where("TYPE", Sql.eq(CloudType.WEBDAV.name)).executeOn(db).use {
|
||||||
|
it.moveToFirst()
|
||||||
|
Assert.assertThat(it.getInt(it.getColumnIndex("_id")), CoreMatchers.`is`(cloudId))
|
||||||
|
Assert.assertThat(it.getString(it.getColumnIndex("ACCESS_TOKEN")), CoreMatchers.`is`(accessToken))
|
||||||
|
Assert.assertThat(it.getString(it.getColumnIndex("URL")), CoreMatchers.`is`(cloudUrl))
|
||||||
|
Assert.assertThat(it.getString(it.getColumnIndex("USERNAME")), CoreMatchers.`is`(username))
|
||||||
|
Assert.assertThat(it.getString(it.getColumnIndex("WEBDAV_CERTIFICATE")), CoreMatchers.`is`(webdavCertificate))
|
||||||
|
}
|
||||||
|
|
||||||
|
Sql.query("VAULT_ENTITY").where("CLOUD_TYPE", Sql.eq(CloudType.WEBDAV.name)).executeOn(db).use {
|
||||||
|
it.moveToFirst()
|
||||||
|
Assert.assertThat(it.getInt(it.getColumnIndex("_id")), CoreMatchers.`is`(vaultId))
|
||||||
|
Assert.assertThat(it.getInt(it.getColumnIndex("FOLDER_CLOUD_ID")), CoreMatchers.`is`(cloudId))
|
||||||
|
Assert.assertThat(it.getString(it.getColumnIndex("FOLDER_PATH")), CoreMatchers.`is`(folderPath))
|
||||||
|
Assert.assertThat(it.getString(it.getColumnIndex("FOLDER_NAME")), CoreMatchers.`is`(folderName))
|
||||||
|
Assert.assertThat(it.getString(it.getColumnIndex("CLOUD_TYPE")), CoreMatchers.`is`(CloudType.WEBDAV.name))
|
||||||
|
Assert.assertThat(it.getString(it.getColumnIndex("PASSWORD")), CoreMatchers.`is`(password))
|
||||||
|
Assert.assertThat(it.getInt(it.getColumnIndex("POSITION")), CoreMatchers.`is`(position))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun upgrade5To6() {
|
||||||
|
Upgrade0To1().applyTo(db, 0)
|
||||||
|
Upgrade1To2().applyTo(db, 1)
|
||||||
|
Upgrade2To3(context).applyTo(db, 2)
|
||||||
|
Upgrade3To4().applyTo(db, 3)
|
||||||
|
Upgrade4To5().applyTo(db, 4)
|
||||||
|
|
||||||
|
val cloudId = 15
|
||||||
|
val cloudUrl = "url"
|
||||||
|
val username = "username"
|
||||||
|
val webdavCertificate = "webdavCertificate"
|
||||||
|
val accessToken = "accessToken"
|
||||||
|
|
||||||
|
val vaultId = 25
|
||||||
|
val folderPath = "path"
|
||||||
|
val folderName = "name"
|
||||||
|
val password = "password"
|
||||||
|
val position = 10
|
||||||
|
|
||||||
|
Sql.insertInto("CLOUD_ENTITY") //
|
||||||
|
.integer("_id", cloudId) //
|
||||||
|
.text("TYPE", CloudType.WEBDAV.name) //
|
||||||
|
.text("ACCESS_TOKEN", accessToken) //
|
||||||
|
.text("URL", cloudUrl) //
|
||||||
|
.text("USERNAME", username) //
|
||||||
|
.text("WEBDAV_CERTIFICATE", webdavCertificate) //
|
||||||
|
.executeOn(db)
|
||||||
|
|
||||||
|
Sql.insertInto("VAULT_ENTITY") //
|
||||||
|
.integer("_id", vaultId) //
|
||||||
|
.integer("FOLDER_CLOUD_ID", cloudId) //
|
||||||
|
.text("FOLDER_PATH", folderPath) //
|
||||||
|
.text("FOLDER_NAME", folderName) //
|
||||||
|
.text("CLOUD_TYPE", CloudType.WEBDAV.name) //
|
||||||
|
.text("PASSWORD", password) //
|
||||||
|
.integer("POSITION", position) //
|
||||||
|
.executeOn(db)
|
||||||
|
|
||||||
|
Upgrade5To6().applyTo(db, 5)
|
||||||
|
|
||||||
|
Sql.query("CLOUD_ENTITY").where("TYPE", Sql.eq(CloudType.WEBDAV.name)).executeOn(db).use {
|
||||||
|
it.moveToFirst()
|
||||||
|
Assert.assertThat(it.getInt(it.getColumnIndex("_id")), CoreMatchers.`is`(cloudId))
|
||||||
|
Assert.assertThat(it.getString(it.getColumnIndex("ACCESS_TOKEN")), CoreMatchers.`is`(accessToken))
|
||||||
|
Assert.assertThat(it.getString(it.getColumnIndex("URL")), CoreMatchers.`is`(cloudUrl))
|
||||||
|
Assert.assertThat(it.getString(it.getColumnIndex("USERNAME")), CoreMatchers.`is`(username))
|
||||||
|
Assert.assertThat(it.getString(it.getColumnIndex("WEBDAV_CERTIFICATE")), CoreMatchers.`is`(webdavCertificate))
|
||||||
|
}
|
||||||
|
|
||||||
|
Sql.query("VAULT_ENTITY").where("CLOUD_TYPE", Sql.eq(CloudType.WEBDAV.name)).executeOn(db).use {
|
||||||
|
it.moveToFirst()
|
||||||
|
Assert.assertThat(it.getInt(it.getColumnIndex("_id")), CoreMatchers.`is`(vaultId))
|
||||||
|
Assert.assertThat(it.getInt(it.getColumnIndex("FOLDER_CLOUD_ID")), CoreMatchers.`is`(cloudId))
|
||||||
|
Assert.assertThat(it.getString(it.getColumnIndex("FOLDER_PATH")), CoreMatchers.`is`(folderPath))
|
||||||
|
Assert.assertThat(it.getString(it.getColumnIndex("FOLDER_NAME")), CoreMatchers.`is`(folderName))
|
||||||
|
Assert.assertThat(it.getString(it.getColumnIndex("CLOUD_TYPE")), CoreMatchers.`is`(CloudType.WEBDAV.name))
|
||||||
|
Assert.assertThat(it.getString(it.getColumnIndex("PASSWORD")), CoreMatchers.`is`(password))
|
||||||
|
Assert.assertThat(it.getInt(it.getColumnIndex("POSITION")), CoreMatchers.`is`(position))
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun upgrade6To7() {
|
||||||
|
Upgrade0To1().applyTo(db, 0)
|
||||||
|
Upgrade1To2().applyTo(db, 1)
|
||||||
|
Upgrade2To3(context).applyTo(db, 2)
|
||||||
|
Upgrade3To4().applyTo(db, 3)
|
||||||
|
Upgrade4To5().applyTo(db, 4)
|
||||||
|
Upgrade5To6().applyTo(db, 5)
|
||||||
|
|
||||||
|
val licenseToken = "licenseToken"
|
||||||
|
val releaseNote = "releaseNote"
|
||||||
|
val version = "version"
|
||||||
|
val urlApk = "urlApk"
|
||||||
|
val urlReleaseNote = "urlReleaseNote"
|
||||||
|
|
||||||
|
Sql.update("UPDATE_CHECK_ENTITY")
|
||||||
|
.set("LICENSE_TOKEN", Sql.toString(licenseToken))
|
||||||
|
.set("RELEASE_NOTE", Sql.toString(releaseNote))
|
||||||
|
.set("VERSION", Sql.toString(version))
|
||||||
|
.set("URL_TO_APK", Sql.toString(urlApk))
|
||||||
|
.set("URL_TO_RELEASE_NOTE", Sql.toString(urlReleaseNote))
|
||||||
|
.executeOn(db)
|
||||||
|
|
||||||
|
Upgrade6To7().applyTo(db, 6)
|
||||||
|
|
||||||
|
Sql.query("UPDATE_CHECK_ENTITY").executeOn(db).use {
|
||||||
|
it.moveToFirst()
|
||||||
|
Assert.assertThat(it.getString(it.getColumnIndex("LICENSE_TOKEN")), CoreMatchers.`is`(licenseToken))
|
||||||
|
Assert.assertThat(it.getString(it.getColumnIndex("RELEASE_NOTE")), CoreMatchers.`is`(releaseNote))
|
||||||
|
Assert.assertThat(it.getString(it.getColumnIndex("VERSION")), CoreMatchers.`is`(version))
|
||||||
|
Assert.assertThat(it.getString(it.getColumnIndex("URL_TO_APK")), CoreMatchers.`is`(urlApk))
|
||||||
|
Assert.assertThat(it.getString(it.getColumnIndex("APK_SHA256")), CoreMatchers.nullValue())
|
||||||
|
Assert.assertThat(it.getString(it.getColumnIndex("URL_TO_RELEASE_NOTE")), CoreMatchers.`is`(urlReleaseNote))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun recoverUpgrade6to7DueToSQLiteExceptionThrown() {
|
||||||
|
Upgrade0To1().applyTo(db, 0)
|
||||||
|
Upgrade1To2().applyTo(db, 1)
|
||||||
|
Upgrade2To3(context).applyTo(db, 2)
|
||||||
|
Upgrade3To4().applyTo(db, 3)
|
||||||
|
Upgrade4To5().applyTo(db, 4)
|
||||||
|
Upgrade5To6().applyTo(db, 5)
|
||||||
|
|
||||||
|
val licenseToken = "licenseToken"
|
||||||
|
|
||||||
|
Sql.update("UPDATE_CHECK_ENTITY")
|
||||||
|
.set("LICENSE_TOKEN", Sql.toString(licenseToken))
|
||||||
|
.set("RELEASE_NOTE", Sql.toString("releaseNote"))
|
||||||
|
.set("VERSION", Sql.toString("version"))
|
||||||
|
.set("URL_TO_APK", Sql.toString("urlApk"))
|
||||||
|
.set("URL_TO_RELEASE_NOTE", Sql.toString("urlReleaseNote"))
|
||||||
|
.executeOn(db)
|
||||||
|
|
||||||
|
Sql.alterTable("UPDATE_CHECK_ENTITY").renameTo("UPDATE_CHECK_ENTITY_OLD").executeOn(db)
|
||||||
|
|
||||||
|
Sql.createTable("UPDATE_CHECK_ENTITY") //
|
||||||
|
.id() //
|
||||||
|
.optionalText("LICENSE_TOKEN") //
|
||||||
|
.optionalText("RELEASE_NOTE") //
|
||||||
|
.optionalText("VERSION") //
|
||||||
|
.optionalText("URL_TO_APK") //
|
||||||
|
.optionalText("APK_SHA256") //
|
||||||
|
.optionalText("URL_TO_RELEASE_NOTE") //
|
||||||
|
.executeOn(db)
|
||||||
|
|
||||||
|
Upgrade6To7().tryToRecoverFromSQLiteException(db)
|
||||||
|
|
||||||
|
Sql.query("UPDATE_CHECK_ENTITY").executeOn(db).use {
|
||||||
|
it.moveToFirst()
|
||||||
|
Assert.assertThat(it.getString(it.getColumnIndex("LICENSE_TOKEN")), CoreMatchers.`is`(licenseToken))
|
||||||
|
Assert.assertThat(it.getString(it.getColumnIndex("RELEASE_NOTE")), CoreMatchers.nullValue())
|
||||||
|
Assert.assertThat(it.getString(it.getColumnIndex("VERSION")), CoreMatchers.nullValue())
|
||||||
|
Assert.assertThat(it.getString(it.getColumnIndex("URL_TO_APK")), CoreMatchers.nullValue())
|
||||||
|
Assert.assertThat(it.getString(it.getColumnIndex("APK_SHA256")), CoreMatchers.nullValue())
|
||||||
|
Assert.assertThat(it.getString(it.getColumnIndex("URL_TO_RELEASE_NOTE")), CoreMatchers.nullValue())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun upgrade7To8() {
|
||||||
|
Upgrade0To1().applyTo(db, 0)
|
||||||
|
Upgrade1To2().applyTo(db, 1)
|
||||||
|
Upgrade2To3(context).applyTo(db, 2)
|
||||||
|
Upgrade3To4().applyTo(db, 3)
|
||||||
|
Upgrade4To5().applyTo(db, 4)
|
||||||
|
Upgrade5To6().applyTo(db, 5)
|
||||||
|
Upgrade6To7().applyTo(db, 6)
|
||||||
|
|
||||||
|
Sql.insertInto("CLOUD_ENTITY") //
|
||||||
|
.integer("_id", 15) //
|
||||||
|
.text("TYPE", CloudType.S3.name) //
|
||||||
|
.text("URL", "url") //
|
||||||
|
.text("USERNAME", "username") //
|
||||||
|
.text("WEBDAV_CERTIFICATE", "certificate") //
|
||||||
|
.text("ACCESS_TOKEN", "accessToken")
|
||||||
|
.text("S3_BUCKET", "s3Bucket") //
|
||||||
|
.text("S3_REGION", "s3Region") //
|
||||||
|
.text("S3_SECRET_KEY", "s3SecretKey") //
|
||||||
|
.executeOn(db)
|
||||||
|
|
||||||
|
Sql.insertInto("VAULT_ENTITY") //
|
||||||
|
.integer("_id", 25) //
|
||||||
|
.integer("FOLDER_CLOUD_ID", 15) //
|
||||||
|
.text("FOLDER_PATH", "path") //
|
||||||
|
.text("FOLDER_NAME", "name") //
|
||||||
|
.text("CLOUD_TYPE", CloudType.S3.name) //
|
||||||
|
.text("PASSWORD", "password") //
|
||||||
|
.integer("POSITION", 10) //
|
||||||
|
.executeOn(db)
|
||||||
|
|
||||||
|
Sql.query("CLOUD_ENTITY").executeOn(db).use {
|
||||||
|
Assert.assertThat(it.count, CoreMatchers.`is`(5))
|
||||||
|
}
|
||||||
|
|
||||||
|
Upgrade7To8().applyTo(db, 7)
|
||||||
|
|
||||||
|
Sql.query("CLOUD_ENTITY").executeOn(db).use {
|
||||||
|
Assert.assertThat(it.count, CoreMatchers.`is`(4))
|
||||||
|
}
|
||||||
|
|
||||||
|
Sql.query("VAULT_ENTITY").executeOn(db).use {
|
||||||
|
Assert.assertThat(it.moveToFirst(), CoreMatchers.`is`(false))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun upgrade8To9() {
|
||||||
|
Upgrade0To1().applyTo(db, 0)
|
||||||
|
Upgrade1To2().applyTo(db, 1)
|
||||||
|
Upgrade2To3(context).applyTo(db, 2)
|
||||||
|
Upgrade3To4().applyTo(db, 3)
|
||||||
|
Upgrade4To5().applyTo(db, 4)
|
||||||
|
Upgrade5To6().applyTo(db, 5)
|
||||||
|
Upgrade6To7().applyTo(db, 6)
|
||||||
|
Upgrade7To8().applyTo(db, 7)
|
||||||
|
|
||||||
|
sharedPreferencesHandler.setBetaScreenDialogAlreadyShown(true)
|
||||||
|
|
||||||
|
Upgrade8To9(sharedPreferencesHandler).applyTo(db, 8)
|
||||||
|
|
||||||
|
Assert.assertThat(sharedPreferencesHandler.isBetaModeAlreadyShown(), CoreMatchers.`is`(false))
|
||||||
|
}
|
||||||
|
}
|
@ -73,7 +73,11 @@ class Sql {
|
|||||||
return (column, contentValues) -> contentValues.put(column, value);
|
return (column, contentValues) -> contentValues.put(column, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ValueHolder toInteger(final Long value) {
|
public static ValueHolder toLong(final Long value) {
|
||||||
|
return (column, contentValues) -> contentValues.put(column, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ValueHolder toInteger(final Integer value) {
|
||||||
return (column, contentValues) -> contentValues.put(column, value);
|
return (column, contentValues) -> contentValues.put(column, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -243,7 +247,6 @@ class Sql {
|
|||||||
public static class SqlAlterTableBuilder {
|
public static class SqlAlterTableBuilder {
|
||||||
|
|
||||||
private final String table;
|
private final String table;
|
||||||
private final StringBuilder columns = new StringBuilder();
|
|
||||||
private String newName;
|
private String newName;
|
||||||
|
|
||||||
private SqlAlterTableBuilder(String table) {
|
private SqlAlterTableBuilder(String table) {
|
||||||
@ -283,8 +286,7 @@ class Sql {
|
|||||||
|
|
||||||
public void executeOn(Database wrapped) {
|
public void executeOn(Database wrapped) {
|
||||||
SQLiteDatabase db = unwrap(wrapped);
|
SQLiteDatabase db = unwrap(wrapped);
|
||||||
StringBuilder query = new StringBuilder() //
|
StringBuilder query = new StringBuilder().append("INSERT INTO \"").append(table).append("\" (");
|
||||||
.append("INSERT INTO \"").append(table).append("\" (");
|
|
||||||
appendColumns(query, columns, false);
|
appendColumns(query, columns, false);
|
||||||
query.append(") SELECT ");
|
query.append(") SELECT ");
|
||||||
appendColumns(query, selectedColumns, true);
|
appendColumns(query, selectedColumns, true);
|
||||||
|
@ -32,7 +32,7 @@ internal class Upgrade1To2 @Inject constructor() : DatabaseUpgrade(1, 2) {
|
|||||||
private fun createInitialUpdateStatus(db: Database) {
|
private fun createInitialUpdateStatus(db: Database) {
|
||||||
Sql.insertInto("UPDATE_CHECK_ENTITY") //
|
Sql.insertInto("UPDATE_CHECK_ENTITY") //
|
||||||
.integer("_id", 1) //
|
.integer("_id", 1) //
|
||||||
.bool("LICENSE_TOKEN", null) //
|
.text("LICENSE_TOKEN", null) //
|
||||||
.text("RELEASE_NOTE", null) //
|
.text("RELEASE_NOTE", null) //
|
||||||
.text("VERSION", null) //
|
.text("VERSION", null) //
|
||||||
.text("URL_TO_APK", null) //
|
.text("URL_TO_APK", null) //
|
||||||
|
@ -20,13 +20,15 @@ internal class Upgrade2To3 @Inject constructor(private val context: Context) : D
|
|||||||
if (it.moveToFirst()) {
|
if (it.moveToFirst()) {
|
||||||
Sql.update("CLOUD_ENTITY")
|
Sql.update("CLOUD_ENTITY")
|
||||||
.set("ACCESS_TOKEN", Sql.toString(encrypt(it.getString(it.getColumnIndex("ACCESS_TOKEN")))))
|
.set("ACCESS_TOKEN", Sql.toString(encrypt(it.getString(it.getColumnIndex("ACCESS_TOKEN")))))
|
||||||
.where("TYPE", Sql.eq("DROPBOX"));
|
.where("TYPE", Sql.eq("DROPBOX"))
|
||||||
|
.executeOn(db)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Sql.update("CLOUD_ENTITY")
|
Sql.update("CLOUD_ENTITY")
|
||||||
.set("ACCESS_TOKEN", Sql.toString(encrypt(onedriveToken())))
|
.set("ACCESS_TOKEN", Sql.toString(encrypt(onedriveToken())))
|
||||||
.where("TYPE", Sql.eq("ONEDRIVE"));
|
.where("TYPE", Sql.eq("ONEDRIVE"))
|
||||||
|
.executeOn(db)
|
||||||
|
|
||||||
db.setTransactionSuccessful()
|
db.setTransactionSuccessful()
|
||||||
} finally {
|
} finally {
|
||||||
|
@ -1,10 +1,7 @@
|
|||||||
package org.cryptomator.data.db
|
package org.cryptomator.data.db
|
||||||
|
|
||||||
import org.cryptomator.data.db.Sql.SqlCreateTableBuilder.ForeignKeyBehaviour
|
import org.cryptomator.data.db.Sql.SqlCreateTableBuilder.ForeignKeyBehaviour
|
||||||
import org.cryptomator.data.db.entities.CloudEntityDao
|
|
||||||
import org.cryptomator.data.db.entities.VaultEntityDao
|
|
||||||
import org.greenrobot.greendao.database.Database
|
import org.greenrobot.greendao.database.Database
|
||||||
import org.greenrobot.greendao.internal.DaoConfig
|
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
|
|
||||||
@ -54,13 +51,13 @@ internal class Upgrade3To4 @Inject constructor() : DatabaseUpgrade(3, 4) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun initVaultPositionUsingCurrentSortOrder(db: Database) {
|
private fun initVaultPositionUsingCurrentSortOrder(db: Database) {
|
||||||
CloudEntityDao(DaoConfig(db, VaultEntityDao::class.java)) //
|
Sql.query("VAULT_ENTITY").executeOn(db).use {
|
||||||
.loadAll() //
|
while (it.moveToNext()) {
|
||||||
.map {
|
Sql.update("VAULT_ENTITY")
|
||||||
Sql.update("VAULT_ENTITY") //
|
.where("_id", Sql.eq(it.getLong(it.getColumnIndex("_id"))))
|
||||||
.where("_id", Sql.eq(it.id)) //
|
.set("POSITION", Sql.toInteger(it.position))
|
||||||
.set("POSITION", Sql.toInteger(it.id - 1)) //
|
|
||||||
.executeOn(db)
|
.executeOn(db)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
package org.cryptomator.data.db
|
package org.cryptomator.data.db
|
||||||
|
|
||||||
|
import android.database.sqlite.SQLiteException
|
||||||
import org.greenrobot.greendao.database.Database
|
import org.greenrobot.greendao.database.Database
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
|
import timber.log.Timber
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
internal class Upgrade6To7 @Inject constructor() : DatabaseUpgrade(6, 7) {
|
internal class Upgrade6To7 @Inject constructor() : DatabaseUpgrade(6, 7) {
|
||||||
@ -30,12 +32,41 @@ internal class Upgrade6To7 @Inject constructor() : DatabaseUpgrade(6, 7) {
|
|||||||
.optionalText("URL_TO_RELEASE_NOTE") //
|
.optionalText("URL_TO_RELEASE_NOTE") //
|
||||||
.executeOn(db)
|
.executeOn(db)
|
||||||
|
|
||||||
Sql.insertInto("UPDATE_CHECK_ENTITY") //
|
try {
|
||||||
.select("_id", "LICENSE_TOKEN", "RELEASE_NOTE", "VERSION", "URL_TO_APK", "URL_TO_RELEASE_NOTE") //
|
Sql.insertInto("UPDATE_CHECK_ENTITY") //
|
||||||
.columns("_id", "LICENSE_TOKEN", "RELEASE_NOTE", "VERSION", "URL_TO_APK", "URL_TO_RELEASE_NOTE") //
|
.select("_id", "LICENSE_TOKEN", "RELEASE_NOTE", "VERSION", "URL_TO_APK", "URL_TO_RELEASE_NOTE") //
|
||||||
.from("UPDATE_CHECK_ENTITY_OLD") //
|
.columns("_id", "LICENSE_TOKEN", "RELEASE_NOTE", "VERSION", "URL_TO_APK", "URL_TO_RELEASE_NOTE") //
|
||||||
.executeOn(db)
|
.from("UPDATE_CHECK_ENTITY_OLD") //
|
||||||
|
.executeOn(db)
|
||||||
|
} catch (e: SQLiteException) {
|
||||||
|
Timber.tag("Upgrade6To7").e(e, "Failed to recover data from old update check entity, insert new initial entry. More details in #336")
|
||||||
|
tryToRecoverFromSQLiteException(db)
|
||||||
|
}
|
||||||
|
|
||||||
Sql.dropTable("UPDATE_CHECK_ENTITY_OLD").executeOn(db)
|
Sql.dropTable("UPDATE_CHECK_ENTITY_OLD").executeOn(db)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun tryToRecoverFromSQLiteException(db: Database) {
|
||||||
|
var licenseToken: String? = null
|
||||||
|
|
||||||
|
try {
|
||||||
|
Sql.query("UPDATE_CHECK_ENTITY_OLD").executeOn(db).use {
|
||||||
|
if (it.moveToNext()) {
|
||||||
|
licenseToken = it.getString(it.getColumnIndex("LICENSE_TOKEN"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e: SQLiteException) {
|
||||||
|
Timber.tag("Upgrade6To7").e(e, "Failed to recover license token while recovery, clear license token if used.")
|
||||||
|
}
|
||||||
|
|
||||||
|
Sql.insertInto("UPDATE_CHECK_ENTITY") //
|
||||||
|
.integer("_id", 1) //
|
||||||
|
.text("LICENSE_TOKEN", licenseToken) //
|
||||||
|
.text("RELEASE_NOTE", null) //
|
||||||
|
.text("VERSION", null) //
|
||||||
|
.text("URL_TO_APK", null) //
|
||||||
|
.text("APK_SHA256", null) //
|
||||||
|
.text("URL_TO_RELEASE_NOTE", null) //
|
||||||
|
.executeOn(db)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@ package org.cryptomator.data.cloud.googledrive
|
|||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import com.google.api.client.http.javanet.NetHttpTransport
|
import com.google.api.client.http.javanet.NetHttpTransport
|
||||||
import com.google.api.client.json.jackson2.JacksonFactory
|
import com.google.api.client.json.gson.GsonFactory
|
||||||
import com.google.api.services.drive.Drive
|
import com.google.api.services.drive.Drive
|
||||||
import com.google.api.services.drive.DriveScopes
|
import com.google.api.services.drive.DriveScopes
|
||||||
import org.cryptomator.data.BuildConfig
|
import org.cryptomator.data.BuildConfig
|
||||||
@ -46,7 +46,7 @@ class GoogleDriveClientFactory internal constructor() {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
val credential = FixedGoogleAccountCredential.usingOAuth2(context, setOf(DriveScopes.DRIVE)).also { it.setAccountName(accountName) }
|
val credential = FixedGoogleAccountCredential.usingOAuth2(context, setOf(DriveScopes.DRIVE)).also { it.setAccountName(accountName) }
|
||||||
return Drive.Builder(NetHttpTransport(), JacksonFactory.getDefaultInstance(), credential) //
|
return Drive.Builder(NetHttpTransport(), GsonFactory.getDefaultInstance(), credential) //
|
||||||
.setApplicationName("Cryptomator-Android/" + BuildConfig.VERSION_NAME) //
|
.setApplicationName("Cryptomator-Android/" + BuildConfig.VERSION_NAME) //
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
|
@ -1,3 +1,8 @@
|
|||||||
- Unterstützung für S3-kompatiblen Speicher hinzugefügt
|
- Kompatibilität zur Tresor-Format 8 hinzugefügt
|
||||||
- Passwortrichtlinie verbessert, so dass Tresore mit sehr schlechten Passwörtern nicht mehr erstellt werden können
|
- Google-Login in pCloud hinzugefügt
|
||||||
- Problem bei der Dateisuche behoben, falls Globbing aktiviert, die Live-Suche deaktiviert und das Muster Großbuchstaben enthält
|
- Geteilte Tresore in pCloud hinzugefügt
|
||||||
|
- Eine Menge Übersetzungen hinzugefügt, ein großes Lob an die Mitwirkenden
|
||||||
|
- Minimale Android-Version auf 7 erhöht (Anmerkung: Android 6 hat fast 2 Jahre lang keine Sicherheitsupdates erhalten)
|
||||||
|
- Auto-Updater des APK-Stores verbessert
|
||||||
|
- Tresorname in S3 kann wieder umbenannt werden
|
||||||
|
- Kompatibilität für schwache biometrische Authentifikatoren eingestellt
|
@ -1,3 +1,8 @@
|
|||||||
- Added support for S3 compatible storage
|
- Added compatibility to vault format 8
|
||||||
- Enhanced password policy so that vaults with very bad passwords can no longer be created
|
- Added Google login in pCloud
|
||||||
- Fixed problem in file search when globbing is enabled, live search is disabled and pattern contains uppercase characters
|
- Added shared vaults in pCloud
|
||||||
|
- Added a ton of translations, kudos to our contributors
|
||||||
|
- Enhanced auto updater of APK store
|
||||||
|
- Increased min. Android version to 7 (Side note: Android 6 did not receive security updates for almost 2 years)
|
||||||
|
- Fixed rename vault name in S3
|
||||||
|
- Dropped support for weak biometric authenticators
|
@ -1,5 +1,10 @@
|
|||||||
<ul>
|
<ul>
|
||||||
<li>Added support for S3 compatible storage</li>
|
<li>Added compatibility to vault format 8</li>
|
||||||
<li>Enhanced password policy so that vaults with very bad passwords can no longer be created</li>
|
<li>Added Google login in pCloud</li>
|
||||||
<li>Fixed problem in file search when globbing is enabled, live search is disabled and pattern contains uppercase characters</li>
|
<li>Added shared vaults in pCloud</li>
|
||||||
|
<li>Added a ton of translations, kudos to our contributors</li>
|
||||||
|
<li>Enhanced auto updater of APK store</li>
|
||||||
|
<li>Increased min. Android version to 7 (Side note: Android 6 did not receive security updates for almost 2 years)</li>
|
||||||
|
<li>Fixed rename vault name in S3</li>
|
||||||
|
<li>Dropped support for weak biometric authenticators</li>
|
||||||
</ul>
|
</ul>
|
@ -80,7 +80,9 @@
|
|||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
<activity android:name=".ui.activity.AutoUploadChooseVaultActivity" />
|
<activity
|
||||||
|
android:name=".ui.activity.UnlockVaultActivity"
|
||||||
|
android:theme="@style/TransparentPopUp" />
|
||||||
|
|
||||||
<!-- Cloud Services -->
|
<!-- Cloud Services -->
|
||||||
<activity
|
<activity
|
||||||
@ -97,13 +99,9 @@
|
|||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
<activity
|
|
||||||
android:name=".ui.activity.UnlockVaultActivity"
|
|
||||||
android:label=""
|
|
||||||
android:theme="@style/TransparentAlertDialogCustom" />
|
|
||||||
<activity android:name=".ui.activity.EmptyDirIdFileInfoActivity" />
|
|
||||||
|
|
||||||
<!-- Settings -->
|
<!-- Settings -->
|
||||||
|
<activity android:name=".ui.activity.AutoUploadChooseVaultActivity" />
|
||||||
|
<activity android:name=".ui.activity.EmptyDirIdFileInfoActivity" />
|
||||||
<activity android:name=".ui.activity.BiometricAuthSettingsActivity" />
|
<activity android:name=".ui.activity.BiometricAuthSettingsActivity" />
|
||||||
<activity android:name=".ui.activity.CloudConnectionListActivity" />
|
<activity android:name=".ui.activity.CloudConnectionListActivity" />
|
||||||
<activity android:name=".ui.activity.CloudSettingsActivity" />
|
<activity android:name=".ui.activity.CloudSettingsActivity" />
|
||||||
|
@ -433,7 +433,7 @@ class BrowseFilesPresenter @Inject constructor( //
|
|||||||
Intents.textEditorIntent() //
|
Intents.textEditorIntent() //
|
||||||
.withTextFile(cloudFile)
|
.withTextFile(cloudFile)
|
||||||
)
|
)
|
||||||
} else if (!lowerFileName.endsWith(".gif") && mimeTypes.fromFilename(cloudFile.name) ?: (MimeType.WILDCARD_MIME_TYPE).mediatype == "image") {
|
} else if (!lowerFileName.endsWith(".gif") && isImageMediaType(cloudFile.name)) {
|
||||||
val cloudFileNodes = previewCloudFileNodes
|
val cloudFileNodes = previewCloudFileNodes
|
||||||
val imagePreviewStore = ImagePreviewFilesStore( //
|
val imagePreviewStore = ImagePreviewFilesStore( //
|
||||||
cloudFileNodes, //
|
cloudFileNodes, //
|
||||||
@ -448,6 +448,10 @@ class BrowseFilesPresenter @Inject constructor( //
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun isImageMediaType(filename: String): Boolean {
|
||||||
|
return (mimeTypes.fromFilename(filename) ?: MimeType.WILDCARD_MIME_TYPE).mediatype == "image"
|
||||||
|
}
|
||||||
|
|
||||||
private fun viewExternalFile(cloudFile: CloudFileModel) {
|
private fun viewExternalFile(cloudFile: CloudFileModel) {
|
||||||
val viewFileIntent = Intent(Intent.ACTION_VIEW)
|
val viewFileIntent = Intent(Intent.ACTION_VIEW)
|
||||||
fileUtil.contentUriFor(cloudFile).let {
|
fileUtil.contentUriFor(cloudFile).let {
|
||||||
@ -475,8 +479,7 @@ class BrowseFilesPresenter @Inject constructor( //
|
|||||||
view?.renderedCloudNodes()
|
view?.renderedCloudNodes()
|
||||||
?.filterIsInstance<CloudFileModel>()
|
?.filterIsInstance<CloudFileModel>()
|
||||||
?.filterTo(previewCloudFiles) {
|
?.filterTo(previewCloudFiles) {
|
||||||
!it.name.endsWith(".gif") //
|
!it.name.endsWith(".gif") && isImageMediaType(it.name)
|
||||||
&& mimeTypes.fromFilename(it.name) ?: (MimeType.WILDCARD_MIME_TYPE).mediatype == "image"
|
|
||||||
}
|
}
|
||||||
return previewCloudFiles
|
return previewCloudFiles
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,15 @@
|
|||||||
<resources>
|
<resources>
|
||||||
|
|
||||||
<style name="FullscreenTheme" parent="AppTheme">
|
<style name="FullscreenTheme" parent="AppTheme">
|
||||||
|
<item name="android:navigationBarColor">@color/colorBlackTransparent</item>
|
||||||
<!-- windowIsTranslucent=false due to https://issuetracker.google.com/issues/68454482 see #467 -->
|
<!-- windowIsTranslucent=false due to https://issuetracker.google.com/issues/68454482 see #467 -->
|
||||||
<item name="android:windowTranslucentStatus">false</item>
|
<item name="android:windowTranslucentStatus">false</item>
|
||||||
<item name="android:navigationBarColor">@color/colorBlackTransparent</item>
|
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
<style name="TransparentPopUp" parent="AppTheme">
|
||||||
|
<item name="android:windowBackground">@color/colorPrimaryTransparent</item>
|
||||||
|
<!-- windowIsTranslucent=false due to https://issuetracker.google.com/issues/68454482 see #467 -->
|
||||||
|
<item name="android:windowIsTranslucent">false</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
14
presentation/src/main/res/values-v27/styles.xml
Normal file
14
presentation/src/main/res/values-v27/styles.xml
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
<resources>
|
||||||
|
|
||||||
|
<!-- keep in sync with default style -->
|
||||||
|
<style name="FullscreenTheme" parent="AppTheme">
|
||||||
|
<item name="android:windowBackground">@null</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<!-- keep in sync with default style -->
|
||||||
|
<style name="TransparentPopUp" parent="AppTheme">
|
||||||
|
<item name="android:windowBackground">@android:color/transparent</item>
|
||||||
|
<item name="android:windowIsTranslucent">true</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
|
</resources>
|
@ -29,10 +29,6 @@
|
|||||||
<item name="colorAccent">@color/colorPrimary</item>
|
<item name="colorAccent">@color/colorPrimary</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style name="TransparentAlertDialogCustom" parent="AlertDialogCustom">
|
|
||||||
<item name="android:windowBackground">@android:color/transparent</item>
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<style name="Toolbar.Theme" parent="ThemeOverlay.AppCompat.Dark.ActionBar">
|
<style name="Toolbar.Theme" parent="ThemeOverlay.AppCompat.Dark.ActionBar">
|
||||||
<item name="colorAccent">@color/textColorWhite</item>
|
<item name="colorAccent">@color/textColorWhite</item>
|
||||||
</style>
|
</style>
|
||||||
@ -116,8 +112,15 @@
|
|||||||
<item name="android:windowAnimationStyle">@null</item>
|
<item name="android:windowAnimationStyle">@null</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
<!-- keep in sync with v27 style -->
|
||||||
<style name="FullscreenTheme" parent="AppTheme">
|
<style name="FullscreenTheme" parent="AppTheme">
|
||||||
<item name="android:windowBackground">@null</item>
|
<item name="android:windowBackground">@null</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
<!-- keep in sync with v27 style -->
|
||||||
|
<style name="TransparentPopUp" parent="AppTheme">
|
||||||
|
<item name="android:windowBackground">@android:color/transparent</item>
|
||||||
|
<item name="android:windowIsTranslucent">true</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user