Skip to content
Open
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
2 changes: 1 addition & 1 deletion Core
Submodule Core updated 32 files
+5 −1 Auth/build.gradle.kts
+203 −0 Auth/schemas/com.infomaniak.core.auth.room.UserDatabase/9.json
+4 −2 Auth/src/main/kotlin/com/infomaniak/core/auth/AbstractCurrentUserAccountUtils.kt
+11 −2 Auth/src/main/kotlin/com/infomaniak/core/auth/CredentialManager.kt
+38 −0 Auth/src/main/kotlin/com/infomaniak/core/auth/DerivedTokenGenerator.IssueExtensions.kt
+2 −2 Auth/src/main/kotlin/com/infomaniak/core/auth/DerivedTokenGenerator.kt
+7 −21 Auth/src/main/kotlin/com/infomaniak/core/auth/DerivedTokenGeneratorImpl.kt
+4 −2 Auth/src/main/kotlin/com/infomaniak/core/auth/PersistedCurrentUserAccountUtils.kt
+2 −0 Auth/src/main/kotlin/com/infomaniak/core/auth/TokenInterceptor.kt
+19 −4 Auth/src/main/kotlin/com/infomaniak/core/auth/UserAccountUtils.kt
+66 −0 Auth/src/main/kotlin/com/infomaniak/core/auth/backup/RestoreFromBackupManager.kt
+162 −0 Auth/src/main/kotlin/com/infomaniak/core/auth/backup/RestoreFromBackupManagerImpl.kt
+99 −0 Auth/src/main/kotlin/com/infomaniak/core/auth/backup/RestoringFromBackupFailedScreen.kt
+40 −0 Auth/src/main/kotlin/com/infomaniak/core/auth/models/TokenDeviceBinding.kt
+11 −1 Auth/src/main/kotlin/com/infomaniak/core/auth/room/UserDao.kt
+4 −3 Auth/src/main/kotlin/com/infomaniak/core/auth/room/UserDatabase.kt
+6 −1 Auth/src/test/java/com/infomaniak/core/auth/AccountUtilsCommonTest.kt
+6 −0 Auth/src/test/java/com/infomaniak/core/auth/BaseAccountUtilsTest.kt
+6 −1 Auth/src/test/java/com/infomaniak/core/auth/PersistedUserIdAccountUtilsTest.kt
+1 −0 Common/build.gradle.kts
+28 −0 Common/src/main/kotlin/com/infomaniak/core/common/AndroidId.kt
+26 −0 Common/src/main/kotlin/com/infomaniak/core/common/utils/KotlinDateUtils.kt
+10 −21 CrossAppLogin/Back/src/main/kotlin/com/infomaniak/core/crossapplogin/back/BaseCrossAppLoginViewModel.kt
+1 −7 ...ogin/Back/src/main/kotlin/com/infomaniak/core/crossapplogin/back/internal/deviceid/SharedDeviceIdStorage.kt
+3 −2 CrossAppLogin/README.md
+0 −1 Network/build.gradle.kts
+0 −2 Network/src/main/kotlin/com/infomaniak/core/network/networking/HttpClientConfig.kt
+7 −0 Ui/View/PrimaryPalette/build.gradle.kts
+36 −0 Ui/View/PrimaryPalette/src/main/res/values/attrs.xml
+3 −1 WebView/src/main/kotlin/com/infomaniak/core/webview/ui/components/WebView.kt
+3 −2 gradle/core.versions.toml
+1 −0 settings.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ open class KDriveTest {
if (!uiRealm.isClosed) uiRealm.close()
Realm.deleteRealm(FileController.getRealmConfiguration(userDrive))
if (!Env.USE_CURRENT_USER) {
runBlocking { AccountUtils.removeUser(context, user) }
runBlocking { AccountUtils.removeUser(user.id) }
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ class MenuUiTest : KDriveUiTest() {
@DisplayName("Check UI to add a new kdrive user then log him off")
fun testAddUser() {
// Remove the other user if he's already in the database
runBlocking { AccountUtils.getUserById(Env.NEW_USER_ID)?.let { removeUser(context, it) } }
runBlocking { AccountUtils.getUserById(Env.NEW_USER_ID)?.let { removeUser(it.id) } }
swipeDownNestedScrollView()
getDeviceViewById("changeUserIcon").clickAndWaitForNewWindow()
getDeviceViewById("addUser").clickAndWaitForNewWindow()
Expand Down
5 changes: 3 additions & 2 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -78,17 +78,18 @@

<application
android:name=".MainApplication"
android:allowBackup="false"
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:enableOnBackInvokedCallback="true"
android:fullBackupContent="false"
android:fullBackupContent="@xml/backup_rules"
Comment thread
Elouan1411 marked this conversation as resolved.
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:requestLegacyExternalStorage="true"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme"
android:usesCleartextTraffic="false"
tools:replace="android:allowBackup,android:fullBackupContent"
tools:targetApi="TIRAMISU">

<meta-data
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ object UploadWorkerErrorHandling {
UploadFile.deleteAll(uploadFile.remoteFolder, permanently = true)
if (uploadFile.isSync()) {
Sentry.captureMessage("FolderNotFoundNotification: disableAutoSync")
applicationContext.disableAutoSync()
disableAutoSync()
}
uploadFile.folderNotFoundNotification(applicationContext)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ class MediaObserverWorker(appContext: Context, params: WorkerParameters) : Corou

if (syncSetting == null) {
Sentry.captureMessage("$TAG: disableAutoSync")
context.disableAutoSync()
disableAutoSync()
return
}

Expand Down
22 changes: 22 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 @@ -23,14 +23,18 @@ import android.content.Intent
import android.net.Uri
import android.os.Build.VERSION.SDK_INT
import android.os.Bundle
import androidx.activity.compose.setContent
import androidx.appcompat.app.AppCompatActivity
import androidx.core.net.toUri
import androidx.lifecycle.lifecycleScope
import com.infomaniak.core.auth.backup.RestoreFromBackupManager
import com.infomaniak.core.auth.backup.RestoringFromBackupFailedScreen
import com.infomaniak.core.legacy.extensions.setDefaultLocaleIfNeeded
import com.infomaniak.core.network.models.ApiError
import com.infomaniak.core.network.models.ApiResponseStatus
import com.infomaniak.core.network.models.exceptions.NetworkException
import com.infomaniak.core.sentry.SentryLog
import com.infomaniak.core.ui.compose.materialthemefromxml.MaterialThemeFromXml
import com.infomaniak.core.ui.view.edgetoedge.EdgeToEdgeActivity
import com.infomaniak.drive.MatomoDrive.MatomoName
import com.infomaniak.drive.MatomoDrive.trackDeepLink
Expand Down Expand Up @@ -68,6 +72,8 @@ import io.sentry.Breadcrumb
import io.sentry.Sentry
import io.sentry.SentryLevel
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.transform
import kotlinx.coroutines.invoke
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
Expand All @@ -93,6 +99,7 @@ class LaunchActivity : EdgeToEdgeActivity() {
trackScreen()

lifecycleScope.launch {
handleRestoreFromBackup()
logoutCurrentUserIfNeeded() // Rights v2 migration temporary fix
handleLaunchArgs()
if (deeplinkType?.isHandled == false) {
Expand All @@ -107,6 +114,21 @@ class LaunchActivity : EdgeToEdgeActivity() {
}
}

private suspend fun handleRestoreFromBackup() {
val manager = RestoreFromBackupManager.instance
manager.state.transform { state ->
when (state) {
RestoreFromBackupManager.State.RestoringFromBackup -> {
setContentView(binding.root)
}
is RestoreFromBackupManager.State.RestoringFromBackupFailed -> {
setContent { MaterialThemeFromXml { RestoringFromBackupFailedScreen(state) } }
}
RestoreFromBackupManager.State.Settled -> emit(Unit)
}
}.first()
}

private suspend fun handleLaunchArgs() {
when (val type = LaunchArgsType.from(navigationArgs, intent)) {
is Deeplink -> handleDeeplink(type)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,10 @@ import androidx.lifecycle.lifecycleScope
import com.google.android.material.datepicker.CalendarConstraints
import com.google.android.material.datepicker.DateValidatorPointBackward
import com.google.android.material.datepicker.MaterialDatePicker
import com.infomaniak.core.common.extensions.isNightModeEnabled
import com.infomaniak.core.common.utils.FORMAT_DATE_CLEAR_MONTH
import com.infomaniak.core.common.utils.format
import com.infomaniak.core.common.utils.startOfTheDay
import com.infomaniak.core.common.extensions.isNightModeEnabled
import com.infomaniak.core.legacy.utils.context
import com.infomaniak.core.legacy.utils.startAppSettingsConfig
import com.infomaniak.core.legacy.utils.whenResultIsOk
Expand Down Expand Up @@ -453,7 +453,7 @@ class SyncSettingsActivity : BaseActivity() {
SentryLog.i(TAG, "appSettings updated")
if (oldSyncSettings?.driveId != syncSettings.driveId) {
UploadFile.deleteAllSyncFile()
applicationContext.cancelPeriodicSync()
cancelPeriodicSync()
SentryLog.i(TAG, "New drive detected -> old sync files has been deleted")
}
applicationContext.activateAutoSync(syncSettings)
Expand Down
37 changes: 18 additions & 19 deletions app/src/main/java/com/infomaniak/drive/utils/AccountUtils.kt
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,12 @@ import kotlinx.coroutines.launch
import kotlinx.coroutines.sync.withLock
import kotlinx.coroutines.withContext
import okhttp3.OkHttpClient
import splitties.init.appCtx
import com.infomaniak.core.network.networking.HttpClient.okHttpClient as unauthenticatedHttpClient

object AccountUtils : CredentialManager() {
object AccountUtils : CredentialManager(
userDataCleanableList = { MainApplication.userDataCleanableList }
) {

private const val DISABLE_AUTO_SYNC = "AccountUtils: disableAutoSync"

Expand Down Expand Up @@ -113,12 +116,10 @@ object AccountUtils : CredentialManager() {
return currentUser
}

suspend fun addUser(user: User) {
override suspend fun addUser(user: User) {
currentDriveId = -1
currentUser = user
val userId = user.id.toLong()
MainApplication.userDataCleanableList.forEach { it.resetForUser(userId) }
userDatabase.userDao().insert(user)
super.addUser(user)
}

suspend fun updateCurrentUserAndDrives(
Expand Down Expand Up @@ -165,7 +166,7 @@ object AccountUtils : CredentialManager() {
for (driveRemoved in driveRemovedList) {
if (appSyncSettings?.userId == user.id && appSyncSettings.driveId == driveRemoved.id) {
Sentry.captureMessage(DISABLE_AUTO_SYNC)
context.disableAutoSync()
disableAutoSync()
}
if (currentDriveId == driveRemoved.id) {
getFirstDrive()
Expand Down Expand Up @@ -220,31 +221,29 @@ object AccountUtils : CredentialManager() {
}
}

MyKSuiteDataUtils.deleteData(user.id)
removeUser(context, user)
removeUser(user.id)
}

suspend fun removeUser(context: Context, user: User) {
val userId = user.id.toLong()
MainApplication.userDataCleanableList.forEach { it.resetForUser(userId) }
userDatabase.userDao().delete(user)
FileController.deleteUserDriveFiles(user.id)
override suspend fun removeUser(userId: Int) {
MyKSuiteDataUtils.deleteData(userId)
super.removeUser(userId)
FileController.deleteUserDriveFiles(userId)

if (UploadFile.getAppSyncSettings()?.userId == user.id) {
if (UploadFile.getAppSyncSettings()?.userId == userId) {
Sentry.captureMessage(DISABLE_AUTO_SYNC)
context.disableAutoSync()
disableAutoSync()
}

if (currentUserId == user.id) {
if (currentUserId == userId) {
requestCurrentUser()
currentDriveId = -1

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

CloudStorageProvider.notifyRootsChanged(context)
CloudStorageProvider.notifyRootsChanged(appCtx)
}
}

Expand Down Expand Up @@ -281,7 +280,7 @@ object AccountUtils : CredentialManager() {

if (isEnableAppSync()) {
Sentry.captureMessage(DISABLE_AUTO_SYNC)
context.disableAutoSync()
disableAutoSync()
}

// Delete all app data
Expand Down
13 changes: 7 additions & 6 deletions app/src/main/java/com/infomaniak/drive/utils/SyncUtils.kt
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import com.infomaniak.drive.data.services.PeriodicUploadWorker
import com.infomaniak.drive.data.services.UploadWorker
import com.infomaniak.drive.data.sync.MediaObserverWorker
import kotlinx.coroutines.flow.first
import splitties.init.appCtx

object SyncUtils {

Expand Down Expand Up @@ -89,9 +90,9 @@ object SyncUtils {
}
}

fun Context.cancelPeriodicSync() {
WorkManager.getInstance(this).cancelUniqueWork(UploadWorker.TAG)
WorkManager.getInstance(this).cancelUniqueWork(PeriodicUploadWorker.TAG)
fun cancelPeriodicSync() {
WorkManager.getInstance(appCtx).cancelUniqueWork(UploadWorker.TAG)
WorkManager.getInstance(appCtx).cancelUniqueWork(PeriodicUploadWorker.TAG)
}

suspend fun Context.activateSyncIfNeeded() {
Expand All @@ -112,8 +113,8 @@ object SyncUtils {
}
}

private fun Context.cancelContentObserver() {
MediaObserverWorker.cancelWork(applicationContext)
private fun cancelContentObserver() {
MediaObserverWorker.cancelWork(appCtx)
}

suspend fun Context.activateAutoSync(syncSettings: SyncSettings) {
Expand All @@ -122,7 +123,7 @@ object SyncUtils {
startPeriodicSync(context = this, syncSettings.syncInterval)
}

fun Context.disableAutoSync() {
fun disableAutoSync() {
UploadFile.removeAppSyncSettings()
MediaFolder.deleteAll()
cancelContentObserver()
Expand Down
21 changes: 21 additions & 0 deletions app/src/main/res/xml/backup_rules.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?><!--
~ Infomaniak kDrive - Android
~ Copyright (C) 2026 Infomaniak Network SA
~
~ This program is free software: you can redistribute it and/or modify
~ it under the terms of the GNU General Public License as published by
~ the Free Software Foundation, either version 3 of the License, or
~ (at your option) any later version.
~
~ This program is distributed in the hope that it will be useful,
~ but WITHOUT ANY WARRANTY; without even the implied warranty of
~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
~ GNU General Public License for more details.
~
~ You should have received a copy of the GNU General Public License
~ along with this program. If not, see <http://www.gnu.org/licenses/>.
-->
<full-backup-content>
<include domain="sharedpref" path="." />
<include domain="file" path="datastore/" />
</full-backup-content>
Comment thread
Elouan1411 marked this conversation as resolved.
21 changes: 11 additions & 10 deletions app/src/main/res/xml/data_extraction_rules.xml
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,18 @@
-->
<data-extraction-rules>
<cloud-backup>
<exclude domain="root" />
<exclude domain="file" />
<exclude domain="database" />
<exclude domain="sharedpref" />
<exclude domain="external" />
<include domain="sharedpref" path="." />
<include domain="file" path="datastore/" />
</cloud-backup>
Comment thread
Elouan1411 marked this conversation as resolved.

<device-transfer>
<exclude domain="root" />
<exclude domain="file" />
<exclude domain="database" />
<exclude domain="sharedpref" />
<exclude domain="external" />
<include domain="sharedpref" path="." />
<include domain="file" path="datastore/" />
<include domain="database" path="." />

<include domain="file" path="AppSettings.realm" />
<include domain="file" path="AppSettings.realm.lock" />
<include domain="file" path="AppSettings.realm.note" />
<include domain="file" path="AppSettings.realm.management/" />
</device-transfer>
</data-extraction-rules>
Loading