Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rights migration, temporary fix to v2 #527

Merged
merged 3 commits into from
Feb 9, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 12 additions & 5 deletions app/src/main/java/com/infomaniak/drive/ApplicationMain.kt
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,11 @@ import com.infomaniak.drive.data.models.UiSettings
import com.infomaniak.drive.data.services.MqttClientWrapper
import com.infomaniak.drive.data.sync.UploadNotifications.pendingIntentFlags
import com.infomaniak.drive.ui.LaunchActivity
import com.infomaniak.drive.utils.*
import com.infomaniak.drive.utils.AccountUtils
import com.infomaniak.drive.utils.KDriveHttpClient
import com.infomaniak.drive.utils.NotificationUtils.initNotificationChannel
import com.infomaniak.drive.utils.NotificationUtils.showGeneralNotification
import com.infomaniak.drive.utils.clearStack
import com.infomaniak.lib.core.InfomaniakCore
import com.infomaniak.lib.core.auth.TokenAuthenticator
import com.infomaniak.lib.core.auth.TokenInterceptor
Expand All @@ -54,10 +56,12 @@ import io.sentry.SentryEvent
import io.sentry.SentryOptions
import io.sentry.android.core.SentryAndroid
import io.sentry.android.core.SentryAndroidOptions
import kotlinx.coroutines.*
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import okhttp3.Interceptor
import okhttp3.OkHttpClient
import org.eclipse.paho.client.mqttv3.*
import java.util.*

class ApplicationMain : Application(), ImageLoaderFactory {
Expand Down Expand Up @@ -91,8 +95,11 @@ class ApplicationMain : Application(), ImageLoaderFactory {

runBlocking { initRealm() }

AccountUtils.reloadApp = {
startActivity(Intent(this, LaunchActivity::class.java).clearStack())
AccountUtils.reloadApp = { bundle ->
val intent = Intent(this, LaunchActivity::class.java)
.apply { putExtras(bundle) }
.clearStack()
startActivity(intent)
}

InfomaniakCore.init(
Expand Down
35 changes: 33 additions & 2 deletions app/src/main/java/com/infomaniak/drive/data/cache/FileMigration.kt
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,23 @@
*/
package com.infomaniak.drive.data.cache

import androidx.core.os.bundleOf
import com.infomaniak.drive.data.models.File
import com.infomaniak.drive.data.models.FileCategory
import com.infomaniak.drive.data.models.Rights
import com.infomaniak.drive.utils.AccountUtils
import io.realm.DynamicRealm
import io.realm.FieldAttribute
import io.realm.RealmMigration
import io.realm.RealmSchema
import io.sentry.Sentry
import java.util.*

class FileMigration : RealmMigration {
companion object {
const val bddVersion = 3L // Must be bumped when the schema changes

const val LOGOUT_CURRENT_USER_TAG = "logout_current_user_tag"
}

override fun migrate(realm: DynamicRealm, oldVersion: Long, newVersion: Long) {
Expand Down Expand Up @@ -74,26 +79,37 @@ class FileMigration : RealmMigration {
}
// Rights migration with sentry logs
val sentryLogs = arrayListOf<Pair<Int, String>>()
var countOfflineFiles = 0
runCatching {
schema.get(Rights::class.java.simpleName)?.transform { // apply for each right
val fileId = it.getInt("fileId")
val file = realm.where(File::class.java.simpleName).equalTo(File::id.name, fileId).findFirst()
if (file == null) it.deleteFromRealm() // Delete if it's orphan
sentryLogs.add(fileId to "right is orphan ${file == null}")
if (file == null) {
it.deleteFromRealm() // Delete if it's orphan
sentryLogs.add(fileId to "right is orphan true")
}
// Count offline files for sentry log
if (file?.getBoolean(File::isOffline.name) == true) countOfflineFiles++
}?.apply {
removePrimaryKey()
removeField("fileId")
isEmbedded = true
}

}.onFailure { exception ->
exception.printStackTrace()
// On some clients, it happens that isEmbedded is added in an orphan file without knowing why
// So we add these sentry logs to have more info
// We have an issue here: https://github.com/realm/realm-java/issues/7642
Sentry.withScope { scope ->
scope.setExtra("oldVersion", "$oldVersion")
scope.setExtra("count orphan files", "${sentryLogs.count()}")
scope.setExtra("count offline files", "$countOfflineFiles")
scope.setExtra("logs", sentryLogs.toString())
Sentry.captureException(exception)
}

temporaryMigrationFixToV2(realm, schema)
}

oldVersionTemp++
Expand All @@ -120,4 +136,19 @@ class FileMigration : RealmMigration {
override fun hashCode(): Int {
return javaClass.hashCode()
}

private fun temporaryMigrationFixToV2(realm: DynamicRealm, schema: RealmSchema) {
val offlineFile = realm.where(File::class.java.simpleName).equalTo(File::isOffline.name, true).findFirst()

// Delete all realm DB
realm.deleteAll()
// Continue migration
schema.get(Rights::class.java.simpleName)?.isEmbedded = true

// Logout the current user if there is at least one offline file
offlineFile?.let {
// Logout current user
AccountUtils.reloadApp?.invoke(bundleOf(LOGOUT_CURRENT_USER_TAG to true))
}
}
}
15 changes: 15 additions & 0 deletions app/src/main/java/com/infomaniak/drive/ui/LaunchActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -22,18 +22,24 @@ import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.lifecycleScope
import com.infomaniak.drive.data.cache.DriveInfosController
import com.infomaniak.drive.data.cache.FileMigration
import com.infomaniak.drive.data.models.AppSettings
import com.infomaniak.drive.ui.login.LoginActivity
import com.infomaniak.drive.ui.login.MigrationActivity
import com.infomaniak.drive.ui.login.MigrationActivity.Companion.getOldkDriveUser
import com.infomaniak.drive.utils.AccountUtils
import com.infomaniak.drive.utils.isKeyguardSecure
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext

class LaunchActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
lifecycleScope.launch {

logoutCurrentUserIfNeeded() // Rights v2 migration temporary fix

when {
AccountUtils.requestCurrentUser() == null -> {
if (getOldkDriveUser().isEmpty) {
Expand Down Expand Up @@ -63,4 +69,13 @@ class LaunchActivity : AppCompatActivity() {
super.onPause()
overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out)
}

private suspend fun logoutCurrentUserIfNeeded() = withContext(Dispatchers.IO) {
intent.extras?.getBoolean(FileMigration.LOGOUT_CURRENT_USER_TAG)?.let { needLogoutCurrentUser ->
if (needLogoutCurrentUser) {
if (AccountUtils.currentUser == null) AccountUtils.requestCurrentUser()
AccountUtils.currentUser?.let { AccountUtils.removeUser(this@LaunchActivity, it) }
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ class SwitchDriveDialog : SelectBottomSheetDialog() {
} else {
AccountUtils.currentDriveId = drive.id
(activity as? MainActivity)?.saveLastNavigationItemSelected()
AccountUtils.reloadApp?.invoke()
AccountUtils.reloadApp?.invoke(bundleOf())
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ package com.infomaniak.drive.ui
import android.content.Intent
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.core.os.bundleOf
import com.infomaniak.drive.R
import com.infomaniak.drive.ui.login.LoginActivity
import com.infomaniak.drive.ui.menu.UserAdapter
Expand All @@ -41,7 +42,7 @@ class SwitchUserActivity : AppCompatActivity() {
usersRecyclerView.adapter = UserAdapter(users as ArrayList<User>) { user ->
AccountUtils.currentUser = user
AccountUtils.currentDriveId = -1
AccountUtils.reloadApp?.invoke()
AccountUtils.reloadApp?.invoke(bundleOf())
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ import com.infomaniak.lib.core.models.User
import com.infomaniak.lib.core.networking.HttpClient
import com.infomaniak.lib.login.ApiToken
import com.infomaniak.lib.login.InfomaniakLogin
import kotlinx.android.synthetic.main.activity_login.*
import kotlinx.android.synthetic.main.activity_migration.*
import kotlinx.android.synthetic.main.fragment_intro.view.*
import kotlinx.coroutines.Dispatchers
Expand Down
12 changes: 7 additions & 5 deletions app/src/main/java/com/infomaniak/drive/utils/AccountUtils.kt
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@
package com.infomaniak.drive.utils

import android.content.Context
import android.os.Bundle
import android.util.Log
import androidx.core.os.bundleOf
import androidx.lifecycle.LiveData
import com.facebook.stetho.okhttp3.StethoInterceptor
import com.infomaniak.drive.BuildConfig
Expand Down Expand Up @@ -54,7 +56,7 @@ import java.util.concurrent.TimeUnit
object AccountUtils : CredentialManager {

private lateinit var userDatabase: UserDatabase
var reloadApp: (() -> Unit)? = null
var reloadApp: ((bundle: Bundle) -> Unit)? = null

fun init(context: Context) {
userDatabase = UserDatabase.getDatabase(context)
Expand Down Expand Up @@ -128,7 +130,7 @@ object AccountUtils : CredentialManager {
if (currentDriveId == driveRemoved.id) {
getFirstDrive()
GlobalScope.launch(Dispatchers.Main) {
reloadApp?.invoke()
reloadApp?.invoke(bundleOf())
}
}
FileController.deleteUserDriveFiles(user.id, driveRemoved.id)
Expand All @@ -137,13 +139,13 @@ object AccountUtils : CredentialManager {
if (fromMaintenance) {
if (driveInfo.drives.main.any { drive -> !drive.maintenance }) {
GlobalScope.launch(Dispatchers.Main) {
reloadApp?.invoke()
reloadApp?.invoke(bundleOf())
}
}
} else if (driveInfo.drives.main.all { drive -> drive.maintenance } ||
driveInfo.drives.main.any { drive -> drive.maintenance && drive.id == currentDriveId }) {
GlobalScope.launch(Dispatchers.Main) {
reloadApp?.invoke()
reloadApp?.invoke(bundleOf())
}
}

Expand Down Expand Up @@ -187,7 +189,7 @@ object AccountUtils : CredentialManager {

resetApp(context)
GlobalScope.launch(Dispatchers.Main) {
reloadApp?.invoke()
reloadApp?.invoke(bundleOf())
}

CloudStorageProvider.notifyRootsChanged(context)
Expand Down