Account deactivation: the task does the cleanup

This commit is contained in:
Benoit Marty 2020-04-21 20:41:10 +02:00
parent 045e3d7bae
commit 8c8a84b039
4 changed files with 106 additions and 67 deletions

View file

@ -21,6 +21,7 @@ import im.vector.matrix.android.internal.auth.registration.RegistrationFlowRespo
import im.vector.matrix.android.internal.di.MoshiProvider
import im.vector.matrix.android.internal.di.UserId
import im.vector.matrix.android.internal.network.executeRequest
import im.vector.matrix.android.internal.session.cleanup.CleanupSession
import im.vector.matrix.android.internal.task.Task
import org.greenrobot.eventbus.EventBus
import javax.inject.Inject
@ -35,7 +36,8 @@ internal interface DeactivateAccountTask : Task<DeactivateAccountTask.Params, Un
internal class DefaultDeactivateAccountTask @Inject constructor(
private val accountAPI: AccountAPI,
private val eventBus: EventBus,
@UserId private val userId: String
@UserId private val userId: String,
private val cleanupSession: CleanupSession
) : DeactivateAccountTask {
override suspend fun execute(params: DeactivateAccountTask.Params) {
@ -72,6 +74,6 @@ internal class DefaultDeactivateAccountTask @Inject constructor(
throw throwable
}
// TODO This task should also do the cleanup
cleanupSession.handle()
}
}

View file

@ -0,0 +1,87 @@
/*
* Copyright (c) 2020 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package im.vector.matrix.android.internal.session.cleanup
import im.vector.matrix.android.BuildConfig
import im.vector.matrix.android.internal.SessionManager
import im.vector.matrix.android.internal.auth.SessionParamsStore
import im.vector.matrix.android.internal.crypto.CryptoModule
import im.vector.matrix.android.internal.database.RealmKeysUtils
import im.vector.matrix.android.internal.di.CryptoDatabase
import im.vector.matrix.android.internal.di.SessionCacheDirectory
import im.vector.matrix.android.internal.di.SessionDatabase
import im.vector.matrix.android.internal.di.SessionFilesDirectory
import im.vector.matrix.android.internal.di.SessionId
import im.vector.matrix.android.internal.di.UserMd5
import im.vector.matrix.android.internal.di.WorkManagerProvider
import im.vector.matrix.android.internal.session.SessionModule
import im.vector.matrix.android.internal.session.cache.ClearCacheTask
import io.realm.Realm
import io.realm.RealmConfiguration
import timber.log.Timber
import java.io.File
import javax.inject.Inject
internal class CleanupSession @Inject constructor(
private val workManagerProvider: WorkManagerProvider,
@SessionId private val sessionId: String,
private val sessionManager: SessionManager,
private val sessionParamsStore: SessionParamsStore,
@SessionDatabase private val clearSessionDataTask: ClearCacheTask,
@CryptoDatabase private val clearCryptoDataTask: ClearCacheTask,
@SessionFilesDirectory private val sessionFiles: File,
@SessionCacheDirectory private val sessionCache: File,
private val realmKeysUtils: RealmKeysUtils,
@SessionDatabase private val realmSessionConfiguration: RealmConfiguration,
@CryptoDatabase private val realmCryptoConfiguration: RealmConfiguration,
@UserMd5 private val userMd5: String
) {
suspend fun handle() {
Timber.d("Cleanup: release session...")
sessionManager.releaseSession(sessionId)
Timber.d("Cleanup: cancel pending works...")
workManagerProvider.cancelAllWorks()
Timber.d("Cleanup: delete session params...")
sessionParamsStore.delete(sessionId)
Timber.d("Cleanup: clear session data...")
clearSessionDataTask.execute(Unit)
Timber.d("Cleanup: clear crypto data...")
clearCryptoDataTask.execute(Unit)
Timber.d("Cleanup: clear file system")
sessionFiles.deleteRecursively()
sessionCache.deleteRecursively()
Timber.d("Cleanup: clear the database keys")
realmKeysUtils.clear(SessionModule.getKeyAlias(userMd5))
realmKeysUtils.clear(CryptoModule.getKeyAlias(userMd5))
// Sanity check
if (BuildConfig.DEBUG) {
Realm.getGlobalInstanceCount(realmSessionConfiguration)
.takeIf { it > 0 }
?.let { Timber.e("All realm instance for session has not been closed ($it)") }
Realm.getGlobalInstanceCount(realmCryptoConfiguration)
.takeIf { it > 0 }
?.let { Timber.e("All realm instance for crypto has not been closed ($it)") }
}
}
}

View file

@ -16,29 +16,13 @@
package im.vector.matrix.android.internal.session.signout
import im.vector.matrix.android.BuildConfig
import im.vector.matrix.android.api.failure.Failure
import im.vector.matrix.android.api.failure.MatrixError
import im.vector.matrix.android.internal.SessionManager
import im.vector.matrix.android.internal.auth.SessionParamsStore
import im.vector.matrix.android.internal.crypto.CryptoModule
import im.vector.matrix.android.internal.database.RealmKeysUtils
import im.vector.matrix.android.internal.di.CryptoDatabase
import im.vector.matrix.android.internal.di.SessionCacheDirectory
import im.vector.matrix.android.internal.di.SessionDatabase
import im.vector.matrix.android.internal.di.SessionFilesDirectory
import im.vector.matrix.android.internal.di.SessionId
import im.vector.matrix.android.internal.di.UserMd5
import im.vector.matrix.android.internal.di.WorkManagerProvider
import im.vector.matrix.android.internal.network.executeRequest
import im.vector.matrix.android.internal.session.SessionModule
import im.vector.matrix.android.internal.session.cache.ClearCacheTask
import im.vector.matrix.android.internal.session.cleanup.CleanupSession
import im.vector.matrix.android.internal.task.Task
import io.realm.Realm
import io.realm.RealmConfiguration
import org.greenrobot.eventbus.EventBus
import timber.log.Timber
import java.io.File
import java.net.HttpURLConnection
import javax.inject.Inject
@ -49,20 +33,9 @@ internal interface SignOutTask : Task<SignOutTask.Params, Unit> {
}
internal class DefaultSignOutTask @Inject constructor(
private val workManagerProvider: WorkManagerProvider,
@SessionId private val sessionId: String,
private val signOutAPI: SignOutAPI,
private val sessionManager: SessionManager,
private val sessionParamsStore: SessionParamsStore,
@SessionDatabase private val clearSessionDataTask: ClearCacheTask,
@CryptoDatabase private val clearCryptoDataTask: ClearCacheTask,
@SessionFilesDirectory private val sessionFiles: File,
@SessionCacheDirectory private val sessionCache: File,
private val realmKeysUtils: RealmKeysUtils,
@SessionDatabase private val realmSessionConfiguration: RealmConfiguration,
@CryptoDatabase private val realmCryptoConfiguration: RealmConfiguration,
@UserMd5 private val userMd5: String,
private val eventBus: EventBus
private val eventBus: EventBus,
private val cleanupSession: CleanupSession
) : SignOutTask {
override suspend fun execute(params: SignOutTask.Params) {
@ -87,37 +60,7 @@ internal class DefaultSignOutTask @Inject constructor(
}
}
Timber.d("SignOut: release session...")
sessionManager.releaseSession(sessionId)
Timber.d("SignOut: cancel pending works...")
workManagerProvider.cancelAllWorks()
Timber.d("SignOut: delete session params...")
sessionParamsStore.delete(sessionId)
Timber.d("SignOut: clear session data...")
clearSessionDataTask.execute(Unit)
Timber.d("SignOut: clear crypto data...")
clearCryptoDataTask.execute(Unit)
Timber.d("SignOut: clear file system")
sessionFiles.deleteRecursively()
sessionCache.deleteRecursively()
Timber.d("SignOut: clear the database keys")
realmKeysUtils.clear(SessionModule.getKeyAlias(userMd5))
realmKeysUtils.clear(CryptoModule.getKeyAlias(userMd5))
// Sanity check
if (BuildConfig.DEBUG) {
Realm.getGlobalInstanceCount(realmSessionConfiguration)
.takeIf { it > 0 }
?.let { Timber.e("All realm instance for session has not been closed ($it)") }
Realm.getGlobalInstanceCount(realmCryptoConfiguration)
.takeIf { it > 0 }
?.let { Timber.e("All realm instance for crypto has not been closed ($it)") }
}
Timber.d("SignOut: cleanup session...")
cleanupSession.handle()
}
}

View file

@ -123,8 +123,15 @@ class MainActivity : VectorBaseActivity() {
return
}
when {
args.clearCredentials -> session.signOut(
!args.isUserLoggedOut && !args.isAccountDeactivated,
args.isAccountDeactivated -> {
// Just do the local cleanup
Timber.w("Account deactivated, start app")
sessionHolder.clearActiveSession()
doLocalCleanup()
startNextActivityAndFinish()
}
args.clearCredentials -> session.signOut(
!args.isUserLoggedOut,
object : MatrixCallback<Unit> {
override fun onSuccess(data: Unit) {
Timber.w("SIGN_OUT: success, start app")
@ -137,7 +144,7 @@ class MainActivity : VectorBaseActivity() {
displayError(failure)
}
})
args.clearCache -> session.clearCache(
args.clearCache -> session.clearCache(
object : MatrixCallback<Unit> {
override fun onSuccess(data: Unit) {
doLocalCleanup()