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

[ANDROAPP-2474] Import/Export database #3503

Merged
merged 19 commits into from
Mar 8, 2024
Prev Previous commit
Next Next commit
block login info after importing
Signed-off-by: Pablo <[email protected]>
Balcan committed Mar 7, 2024
commit 3578242481f47fc5cbcf2c70c4b87b2c4de60660
Original file line number Diff line number Diff line change
@@ -122,6 +122,7 @@ class LoginActivity : ActivityGlobalAbstract(), LoginContracts.View {

override fun onDbImportFinished() {
showLoginProgress(false)
blockLoginInfo()
}

companion object {
3 changes: 3 additions & 0 deletions app/src/main/java/org/dhis2/usescases/login/LoginModule.kt
Original file line number Diff line number Diff line change
@@ -11,6 +11,7 @@ import org.dhis2.commons.prefs.PreferenceProvider
import org.dhis2.commons.reporting.CrashReportController
import org.dhis2.commons.resources.ResourceManager
import org.dhis2.commons.schedulers.SchedulerProvider
import org.dhis2.commons.viewmodel.DispatcherProvider
import org.dhis2.data.fingerprint.FingerPrintController
import org.dhis2.data.server.UserManager
import org.dhis2.usescases.login.auth.OpenIdProviders
@@ -29,6 +30,7 @@ class LoginModule(
preferenceProvider: PreferenceProvider,
resourceManager: ResourceManager,
schedulerProvider: SchedulerProvider,
dispatcherProvider: DispatcherProvider,
fingerPrintController: FingerPrintController,
analyticsHelper: AnalyticsHelper,
crashReportController: CrashReportController,
@@ -41,6 +43,7 @@ class LoginModule(
preferenceProvider,
resourceManager,
schedulerProvider,
dispatcherProvider,
fingerPrintController,
analyticsHelper,
crashReportController,
39 changes: 21 additions & 18 deletions app/src/main/java/org/dhis2/usescases/login/LoginViewModel.kt
Original file line number Diff line number Diff line change
@@ -27,6 +27,7 @@ import org.dhis2.commons.prefs.SECURE_USER_NAME
import org.dhis2.commons.reporting.CrashReportController
import org.dhis2.commons.resources.ResourceManager
import org.dhis2.commons.schedulers.SchedulerProvider
import org.dhis2.commons.viewmodel.DispatcherProvider
import org.dhis2.data.fingerprint.FingerPrintController
import org.dhis2.data.fingerprint.Type
import org.dhis2.data.server.UserManager
@@ -39,7 +40,6 @@ import org.dhis2.utils.analytics.DATA_STORE_ANALYTICS_PERMISSION_KEY
import org.dhis2.utils.analytics.LOGIN
import org.dhis2.utils.analytics.SERVER_QR_SCANNER
import org.dhis2.utils.analytics.USER_PROPERTY_SERVER
import org.hisp.dhis.android.core.D2Manager
import org.hisp.dhis.android.core.maintenance.D2Error
import org.hisp.dhis.android.core.maintenance.D2ErrorCode
import org.hisp.dhis.android.core.systeminfo.SystemInfo
@@ -55,6 +55,7 @@ class LoginViewModel(
private val preferenceProvider: PreferenceProvider,
private val resourceManager: ResourceManager,
private val schedulers: SchedulerProvider,
private val dispatchers: DispatcherProvider,
private val fingerPrintController: FingerPrintController,
private val analyticsHelper: AnalyticsHelper,
private val crashReportController: CrashReportController,
@@ -560,24 +561,26 @@ class LoginViewModel(
}

fun onImportDataBase(file: File) {
viewModelScope.launch {
val importResult = async {
D2Manager.getD2().maintenanceModule().databaseImportExport().importDatabase(file)
}
val importedMetadata = try {
importResult.await()
} catch (e: Exception) {
view.displayMessage(resourceManager.parseD2Error(e))
Timber.e(e)
null
}
importedMetadata?.let {
setAccountInfo(it.serverUrl, it.username)
view.setUrl(it.serverUrl)
view.setUser(it.username)
displayManageAccount()
userManager?.let {
viewModelScope.launch {
val importResult = async(dispatchers.io()) {
it.d2.maintenanceModule().databaseImportExport().importDatabase(file)
}
val importedMetadata = try {
importResult.await()
} catch (e: Exception) {
view.displayMessage(resourceManager.parseD2Error(e))
Timber.e(e)
null
}
importedMetadata?.let {
setAccountInfo(it.serverUrl, it.username)
view.setUrl(it.serverUrl)
view.setUser(it.username)
displayManageAccount()
}
view.onDbImportFinished()
}
view.onDbImportFinished()
}
}
}
Original file line number Diff line number Diff line change
@@ -7,6 +7,7 @@ import org.dhis2.commons.prefs.PreferenceProvider
import org.dhis2.commons.reporting.CrashReportController
import org.dhis2.commons.resources.ResourceManager
import org.dhis2.commons.schedulers.SchedulerProvider
import org.dhis2.commons.viewmodel.DispatcherProvider
import org.dhis2.data.fingerprint.FingerPrintController
import org.dhis2.data.server.UserManager
import org.dhis2.utils.analytics.AnalyticsHelper
@@ -16,6 +17,7 @@ class LoginViewModelFactory(
private val preferenceProvider: PreferenceProvider,
private val resources: ResourceManager,
private val schedulerProvider: SchedulerProvider,
private val dispatcherProvider: DispatcherProvider,
private val fingerPrintController: FingerPrintController,
private val analyticsHelper: AnalyticsHelper,
private val crashReportController: CrashReportController,
@@ -28,6 +30,7 @@ class LoginViewModelFactory(
preferenceProvider,
resources,
schedulerProvider,
dispatcherProvider,
fingerPrintController,
analyticsHelper,
crashReportController,
66 changes: 63 additions & 3 deletions app/src/test/java/org/dhis2/usescases/login/LoginViewModelTest.kt
Original file line number Diff line number Diff line change
@@ -4,7 +4,11 @@ import androidx.arch.core.executor.testing.InstantTaskExecutorRule
import io.reactivex.Completable
import io.reactivex.Observable
import io.reactivex.Single
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.StandardTestDispatcher
import kotlinx.coroutines.test.setMain
import org.dhis2.commons.Constants.PREFS_URLS
import org.dhis2.commons.Constants.PREFS_USERS
import org.dhis2.commons.Constants.USER_ASKED_CRASHLYTICS
@@ -15,7 +19,9 @@ import org.dhis2.commons.prefs.SECURE_PASS
import org.dhis2.commons.prefs.SECURE_SERVER_URL
import org.dhis2.commons.prefs.SECURE_USER_NAME
import org.dhis2.commons.reporting.CrashReportController
import org.dhis2.commons.resources.ResourceManager
import org.dhis2.commons.schedulers.SchedulerProvider
import org.dhis2.commons.viewmodel.DispatcherProvider
import org.dhis2.data.fingerprint.FingerPrintController
import org.dhis2.data.fingerprint.FingerPrintResult
import org.dhis2.data.fingerprint.Type
@@ -28,11 +34,13 @@ import org.dhis2.utils.analytics.AnalyticsHelper
import org.dhis2.utils.analytics.CLICK
import org.dhis2.utils.analytics.LOGIN
import org.dhis2.utils.analytics.SERVER_QR_SCANNER
import org.hisp.dhis.android.core.arch.db.access.DatabaseExportMetadata
import org.hisp.dhis.android.core.systeminfo.SystemInfo
import org.hisp.dhis.android.core.user.User
import org.hisp.dhis.android.core.user.openid.IntentWithRequestCode
import org.hisp.dhis.android.core.user.openid.OpenIDConnectConfig
import org.junit.Assert.assertTrue
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.mockito.Mockito
@@ -45,6 +53,8 @@ import org.mockito.kotlin.verify
import org.mockito.kotlin.verifyNoMoreInteractions
import org.mockito.kotlin.whenever
import retrofit2.Response
import java.io.File

class LoginViewModelTest {

@get:Rule
@@ -66,24 +76,44 @@ class LoginViewModelTest {
private val network: NetworkUtils = mock()
private lateinit var loginViewModel: LoginViewModel
private val openidconfig: OpenIDConnectConfig = mock()
private val resourceManager: ResourceManager = mock()
private val testingDispatcher = StandardTestDispatcher()
private val dispatcherProvider = object : DispatcherProvider {
override fun io(): CoroutineDispatcher {
return testingDispatcher
}

override fun computation(): CoroutineDispatcher {
return testingDispatcher
}

override fun ui(): CoroutineDispatcher {
return testingDispatcher
}
}

private fun instantiateLoginViewModel() {
loginViewModel = LoginViewModel(
view,
preferenceProvider,
resourceManager,
schedulers,
dispatcherProvider,
goldfinger,
analyticsHelper,
crashReportController,
network,
userManager,
)
}

private fun instantiateLoginViewModelWithNullUserManager() {
loginViewModel = LoginViewModel(
view,
preferenceProvider,
resourceManager,
schedulers,
dispatcherProvider,
goldfinger,
analyticsHelper,
crashReportController,
@@ -92,6 +122,12 @@ class LoginViewModelTest {
)
}

@OptIn(ExperimentalCoroutinesApi::class)
@Before
fun setUp() {
Dispatchers.setMain(testingDispatcher)
}

@Test
fun `Should go to MainActivity if user is already logged in`() {
whenever(userManager.isUserLoggedIn) doReturn Observable.just(true)
@@ -353,8 +389,8 @@ class LoginViewModelTest {
fun `Should set server and username if user is logged`() {
instantiateLoginViewModel()
mockSystemInfo()
whenever(userManager.userName())doReturn Single.just("Username")
whenever(goldfinger.hasFingerPrint())doReturn true
whenever(userManager.userName()) doReturn Single.just("Username")
whenever(goldfinger.hasFingerPrint()) doReturn true
whenever(preferenceProvider.contains(SECURE_SERVER_URL)) doReturn true
loginViewModel.checkServerInfoAndShowBiometricButton()
verify(view).setUrl("contextPath")
@@ -389,12 +425,36 @@ class LoginViewModelTest {
instantiateLoginViewModelWithNullUserManager()
val openidconfig: OpenIDConnectConfig = mock()
val it: IntentWithRequestCode = mock()
whenever(view.initLogin())doReturn userManager
whenever(view.initLogin()) doReturn userManager
whenever(userManager.logIn(openidconfig)) doReturn Observable.just(it)
instantiateLoginViewModelWithNullUserManager()
loginViewModel.openIdLogin(openidconfig)
verify(view).openOpenIDActivity(it)
}

@Test
fun `Should import database`() {
val mockedDatabase: File = mock()

instantiateLoginViewModel()
whenever(
userManager.d2.maintenanceModule().databaseImportExport()
.importDatabase(mockedDatabase),
) doReturn DatabaseExportMetadata(
0,
"2024-01-01",
"serverUrl",
"userName",
false,
)

loginViewModel.onImportDataBase(mockedDatabase)
testingDispatcher.scheduler.advanceUntilIdle()
verify(view).setUrl("serverUrl")
verify(view).setUser("userName")
verify(view).onDbImportFinished()
}

private fun mockSystemInfo(isUserLoggedIn: Boolean = true) {
whenever(userManager.isUserLoggedIn) doReturn Observable.just(isUserLoggedIn)
if (isUserLoggedIn) {