Skip to content

Commit

Permalink
Implement local storage migration by removing them with a hint #251
Browse files Browse the repository at this point in the history
  • Loading branch information
SailReal committed Oct 27, 2021
1 parent 302a74a commit 810a987
Show file tree
Hide file tree
Showing 8 changed files with 144 additions and 19 deletions.
Expand Up @@ -50,7 +50,7 @@ class UpgradeDatabaseTest {
Upgrade6To7().applyTo(db, 6)
Upgrade7To8().applyTo(db, 7)
Upgrade8To9(sharedPreferencesHandler).applyTo(db, 8)
Upgrade9To10().applyTo(db, 9)
Upgrade9To10(sharedPreferencesHandler).applyTo(db, 9)

CloudEntityDao(DaoConfig(db, CloudEntityDao::class.java)).loadAll()
VaultEntityDao(DaoConfig(db, VaultEntityDao::class.java)).loadAll()
Expand Down Expand Up @@ -446,7 +446,7 @@ class UpgradeDatabaseTest {
Sql.insertInto("VAULT_ENTITY") //
.integer("_id", 26) //
.integer("FOLDER_CLOUD_ID", 4) //
.text("FOLDER_PATH", "path") //
.text("FOLDER_PATH", "pathOfVault26") //
.text("FOLDER_NAME", "name") //
.text("CLOUD_TYPE", CloudType.LOCAL.name) //
.text("PASSWORD", "password") //
Expand All @@ -457,18 +457,17 @@ class UpgradeDatabaseTest {
Assert.assertThat(it.count, CoreMatchers.`is`(5))
}

Upgrade9To10().applyTo(db, 9)
Upgrade9To10(sharedPreferencesHandler).applyTo(db, 9)

Sql.query("VAULT_ENTITY").executeOn(db).use {
it.moveToFirst()
Assert.assertThat(it.getString(it.getColumnIndex("FOLDER_CLOUD_ID")), CoreMatchers.`is`("15"))
it.moveToNext()
Assert.assertThat(it.getString(it.getColumnIndex("FOLDER_CLOUD_ID")), CoreMatchers.nullValue())
Assert.assertThat(it.count, CoreMatchers.`is`(1))
}

Sql.query("CLOUD_ENTITY").executeOn(db).use {
Assert.assertThat(it.count, CoreMatchers.`is`(4))
}

Assert.assertThat(sharedPreferencesHandler.vaultsRemovedDuringMigration(), CoreMatchers.`is`(Pair("LOCAL", arrayListOf("pathOfVault26"))))
}

}
29 changes: 24 additions & 5 deletions data/src/main/java/org/cryptomator/data/db/Upgrade9To10.kt
@@ -1,23 +1,42 @@
package org.cryptomator.data.db

import org.cryptomator.domain.CloudType
import org.cryptomator.util.SharedPreferencesHandler
import org.greenrobot.greendao.database.Database
import javax.inject.Inject
import javax.inject.Singleton
import timber.log.Timber

@Singleton
internal class Upgrade9To10 @Inject constructor() : DatabaseUpgrade(9, 10) {
internal class Upgrade9To10 @Inject constructor(private val sharedPreferencesHandler: SharedPreferencesHandler) : DatabaseUpgrade(9, 10) {

private val defaultLocalStorageCloudId = 4L

override fun internalApplyTo(db: Database, origin: Int) {
db.beginTransaction()

try {
Sql.update("VAULT_ENTITY")
.set("FOLDER_CLOUD_ID", Sql.toString(null))
.where("FOLDER_CLOUD_ID", Sql.eq(4))
Sql.query("VAULT_ENTITY")
.columns(listOf("FOLDER_PATH"))
.where("FOLDER_CLOUD_ID", Sql.eq(defaultLocalStorageCloudId))
.executeOn(db).use {
val vaultsToBeRemoved = ArrayList<String>()
while (it.moveToNext()) {
val folderPath = it.getString(it.getColumnIndex("FOLDER_PATH"))
vaultsToBeRemoved.add(folderPath)
}
if (vaultsToBeRemoved.isNotEmpty()) {
sharedPreferencesHandler.vaultsRemovedDuringMigration(Pair(CloudType.LOCAL.name, vaultsToBeRemoved))
Timber.tag("Upgrade9To10").i("Added %s to the removeDuringMigrations", vaultsToBeRemoved)
}
}

Sql.deleteFrom("VAULT_ENTITY")
.where("FOLDER_CLOUD_ID", Sql.eq(defaultLocalStorageCloudId))
.executeOn(db)

Sql.deleteFrom("CLOUD_ENTITY")
.where("_id", Sql.eq(4))
.where("_id", Sql.eq(defaultLocalStorageCloudId))
.where("TYPE", Sql.eq("LOCAL"))
.executeOn(db)

Expand Down
Expand Up @@ -12,6 +12,7 @@ import org.cryptomator.data.cloud.crypto.CryptoCloud
import org.cryptomator.data.util.NetworkConnectionCheck
import org.cryptomator.domain.Cloud
import org.cryptomator.domain.CloudFolder
import org.cryptomator.domain.CloudType
import org.cryptomator.domain.Vault
import org.cryptomator.domain.di.PerView
import org.cryptomator.domain.exception.license.LicenseNotValidException
Expand Down Expand Up @@ -49,6 +50,7 @@ import org.cryptomator.presentation.ui.dialog.AskForLockScreenDialog
import org.cryptomator.presentation.ui.dialog.EnterPasswordDialog
import org.cryptomator.presentation.ui.dialog.UpdateAppAvailableDialog
import org.cryptomator.presentation.ui.dialog.UpdateAppDialog
import org.cryptomator.presentation.ui.dialog.VaultsRemovedDuringMigrationDialog
import org.cryptomator.presentation.util.FileUtil
import org.cryptomator.presentation.workflow.ActivityResult
import org.cryptomator.presentation.workflow.AddExistingVaultWorkflow
Expand Down Expand Up @@ -103,6 +105,12 @@ class VaultListPresenter @Inject constructor( //
sharedPreferencesHandler.setScreenLockDialogAlreadyShown()
}

sharedPreferencesHandler.vaultsRemovedDuringMigration()?.let {
val cloudNameString = getString(CloudTypeModel.valueOf(CloudType.valueOf(it.first)).displayNameResource)
view?.showDialog(VaultsRemovedDuringMigrationDialog.newInstance(Pair(cloudNameString, it.second)))
sharedPreferencesHandler.vaultsRemovedDuringMigration(null)
}

checkLicense()
}

Expand All @@ -118,9 +126,10 @@ class VaultListPresenter @Inject constructor( //
}

override fun onError(e: Throwable) {
var license: String? = ""
if (e is LicenseNotValidException) {
license = e.license
val license = if (e is LicenseNotValidException) {
e.license
} else {
""
}
val intent = Intent(context(), LicenseCheckActivity::class.java)
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
Expand Down
Expand Up @@ -13,10 +13,10 @@ import kotlinx.android.synthetic.main.dialog_app_is_obscured_info.tv_app_is_obsc
class AppIsObscuredInfoDialog : BaseDialog<Activity>() {

public override fun setupDialog(builder: AlertDialog.Builder): android.app.Dialog {
builder //
return builder //
.setTitle(R.string.dialog_app_is_obscured_info_title) //
.setNeutralButton(R.string.dialog_app_is_obscured_info_neutral_button) { dialog: DialogInterface, _: Int -> dialog.dismiss() }
return builder.create()
.setNeutralButton(R.string.dialog_app_is_obscured_info_neutral_button) { dialog: DialogInterface, _: Int -> dialog.dismiss() } //
.create()
}

override fun disableDialogWhenObscured(): Boolean {
Expand Down
@@ -0,0 +1,47 @@
package org.cryptomator.presentation.ui.dialog

import android.app.Activity
import android.content.DialogInterface
import android.os.Bundle
import androidx.appcompat.app.AlertDialog
import androidx.fragment.app.DialogFragment
import org.cryptomator.generator.Dialog
import org.cryptomator.presentation.R
import kotlinx.android.synthetic.main.dialog_vaults_removed_during_migration.tv_message

@Dialog(R.layout.dialog_vaults_removed_during_migration)
class VaultsRemovedDuringMigrationDialog : BaseDialog<Activity>() {

public override fun setupDialog(builder: AlertDialog.Builder): android.app.Dialog {
val vaultsRemovedDuringMigration = requireArguments().getSerializable(VAULTS_REMOVED_ARG) as Pair<String, ArrayList<String>>

return builder //
.setTitle(String.format(getString(R.string.dialog_vaults_removed_during_migration_title), vaultsRemovedDuringMigration.first)) //
.setNeutralButton(R.string.dialog_vaults_removed_during_migration_neutral_button) { dialog: DialogInterface, _: Int -> dialog.dismiss() }
.create()
}

public override fun setupView() {
val vaultsRemovedDuringMigration = requireArguments().getSerializable(VAULTS_REMOVED_ARG) as Pair<String, ArrayList<String>>

val vaultsRemovedDuringMigrationString = vaultsRemovedDuringMigration
.second
.map { path -> "* $path" }
.reduce { acc, s -> "$acc\n$s" }

tv_message.text = String.format(getString(R.string.dialog_vaults_removed_during_migration_hint), vaultsRemovedDuringMigrationString)
}

companion object {

private const val VAULTS_REMOVED_ARG = "vaultsRemovedArg"

fun newInstance(vaultsRemovedDuringMigration: Pair<String, List<String>>): DialogFragment {
val args = Bundle()
args.putSerializable(VAULTS_REMOVED_ARG, vaultsRemovedDuringMigration)
val fragment = VaultsRemovedDuringMigrationDialog()
fragment.arguments = args
return fragment
}
}
}
@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.core.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">

<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="@dimen/activity_vertical_margin">

<TextView
android:id="@+id/tv_message"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="5dp"
android:text="@string/dialog_vaults_removed_during_migration_hint" />

</RelativeLayout>
</androidx.core.widget.NestedScrollView>
7 changes: 6 additions & 1 deletion presentation/src/main/res/values/strings.xml
Expand Up @@ -166,7 +166,6 @@
<string name="screen_cloud_settings_option_delete" translatable="false">@string/screen_vault_list_vault_action_delete</string>
<string name="screen_cloud_connections_no_connections">Click here to add locations</string>
<string name="screen_cloud_error_webdav_not_supported">Server doesn\'t seem to be WebDAV compatible</string>
<string name="screen_cloud_local_custom_storage_title">Custom locations</string>
<string name="screen_cloud_local_error_no_content_provider">No additional locations available.</string>

<!-- ## screen: webdav settings -->
Expand Down Expand Up @@ -416,6 +415,12 @@
<string name="dialog_app_is_obscured_info_hint">Another app is displaying something on top of Cryptomator (e.g., a blue light filter or night mode app). For security reasons, Cryptomator is disabled.\n\n<a href="https://docs.cryptomator.org/en/1.5/android/settings/#block-app-when-obscured">How to enable Cryptomator</a></string>
<string name="dialog_app_is_obscured_info_neutral_button">Close</string>


<string name="dialog_vaults_removed_during_migration_title">Please re-add vaults for %1s cloud</string>
<string name="dialog_vaults_removed_during_migration_hint">While migrating to this app version we need to remove the following vaults from the app:\n%2s \n\nThose vaults aren\'t removed from the cloud but only from this app. Sorry for the inconvenience and please re-add these vaults to continue working with them.</string>
<string name="dialog_vaults_removed_during_migration_neutral_button" translatable="false">@string/dialog_unable_to_share_positive_button</string>


<string name="dialog_disable_secure_screen_disclaimer_hint">This setting is a security feature and prevents other apps from tricking users into doing things they do not wan\'t to do.\n\nBy disabling, you confirm that you are <a href="https://docs.cryptomator.org/en/1.5/android/settings/#screen-security">aware of the risks</a>.</string>

<string name="dialog_delete_cloud_connection_with_vaults_message">Are you sure you want to remove this cloud connection?</string>
Expand Down
Expand Up @@ -236,6 +236,31 @@ constructor(context: Context) : SharedPreferences.OnSharedPreferenceChangeListen
return defaultSharedPreferences.getBoolean(BACKGROUND_UNLOCK_PREPARATION, true)
}

fun vaultsRemovedDuringMigration(vaultsToBeRemoved: Pair<String, List<String>>?) {
vaultsToBeRemoved?.let {
val vaultsToBeRemovedString = if (it.second.isNotEmpty()) {
it.second.reduce { acc, s -> "$acc,$s" }
} else {
""
}
defaultSharedPreferences.setValue(VAULTS_REMOVED_DURING_MIGRATION_TYPE, it.first)
defaultSharedPreferences.setValue(VAULTS_REMOVED_DURING_MIGRATION, vaultsToBeRemovedString)
} ?: run {
defaultSharedPreferences.setValue(VAULTS_REMOVED_DURING_MIGRATION_TYPE, null)
defaultSharedPreferences.setValue(VAULTS_REMOVED_DURING_MIGRATION, null)
}
}

fun vaultsRemovedDuringMigration(): Pair<String, List<String>>? {
val vaultsRemovedDuringMigrationType = defaultSharedPreferences.getString(VAULTS_REMOVED_DURING_MIGRATION_TYPE, null)
val vaultsRemovedDuringMigration = defaultSharedPreferences.getString(VAULTS_REMOVED_DURING_MIGRATION, null)
return if(vaultsRemovedDuringMigrationType != null && vaultsRemovedDuringMigration != null) {
Pair(vaultsRemovedDuringMigrationType, ArrayList(vaultsRemovedDuringMigration.split(',')))
} else {
null
}
}

companion object {

private const val SCREEN_LOCK_DIALOG_SHOWN = "askForScreenLockDialogShown"
Expand All @@ -248,6 +273,8 @@ constructor(context: Context) : SharedPreferences.OnSharedPreferenceChangeListen
private const val GLOB_SEARCH = "globSearch"
private const val KEEP_UNLOCKED_WHILE_EDITING = "keepUnlockedWhileEditing"
private const val BACKGROUND_UNLOCK_PREPARATION = "backgroundUnlockPreparation"
private const val VAULTS_REMOVED_DURING_MIGRATION = "vaultsRemovedDuringMigration"
private const val VAULTS_REMOVED_DURING_MIGRATION_TYPE = "vaultsRemovedDuringMigrationType"
const val DEBUG_MODE = "debugMode"
const val DISABLE_APP_WHEN_OBSCURED = "disableAppWhenObscured"
const val SECURE_SCREEN = "secureScreen"
Expand Down

0 comments on commit 810a987

Please sign in to comment.