Skip to content

Commit e459269

Browse files
Merge pull request #2104 from Infomaniak/mailbox-validity
fix: Handle `is_valid` API field for Mailboxes
2 parents 58fe888 + 098fa22 commit e459269

14 files changed

+64
-22
lines changed

app/src/main/java/com/infomaniak/mail/data/cache/RealmDatabase.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ object RealmDatabase {
160160

161161
//region Configurations versions
162162
const val USER_INFO_SCHEMA_VERSION = 2L
163-
const val MAILBOX_INFO_SCHEMA_VERSION = 6L
163+
const val MAILBOX_INFO_SCHEMA_VERSION = 7L
164164
const val MAILBOX_CONTENT_SCHEMA_VERSION = 19L
165165
//endregion
166166

app/src/main/java/com/infomaniak/mail/data/cache/RealmMigrations.kt

+33
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@
1818
package com.infomaniak.mail.data.cache
1919

2020
import com.infomaniak.mail.utils.SentryDebug
21+
import io.realm.kotlin.dynamic.DynamicMutableRealmObject
22+
import io.realm.kotlin.dynamic.DynamicRealmObject
23+
import io.realm.kotlin.dynamic.getValue
2124
import io.realm.kotlin.migration.AutomaticSchemaMigration
2225
import io.realm.kotlin.migration.AutomaticSchemaMigration.MigrationContext
2326

@@ -29,6 +32,7 @@ val USER_INFO_MIGRATION = AutomaticSchemaMigration { migrationContext ->
2932
val MAILBOX_INFO_MIGRATION = AutomaticSchemaMigration { migrationContext ->
3033
SentryDebug.addMigrationBreadcrumb(migrationContext)
3134
migrationContext.deleteRealmFromFirstMigration()
35+
migrationContext.keepDefaultValuesAfterSixthMigration()
3236
}
3337

3438
val MAILBOX_CONTENT_MIGRATION = AutomaticSchemaMigration { migrationContext ->
@@ -40,3 +44,32 @@ val MAILBOX_CONTENT_MIGRATION = AutomaticSchemaMigration { migrationContext ->
4044
private fun MigrationContext.deleteRealmFromFirstMigration() {
4145
if (oldRealm.schemaVersion() < 1L) newRealm.deleteAll()
4246
}
47+
48+
/**
49+
* Migrate from version #6
50+
*
51+
* This whole migration needs to be done because of this issue :
52+
* https://github.com/realm/realm-swift/issues/1793
53+
*
54+
* Yes the issue is on the Realm-Swift repository, but all Realm projects are impacted.
55+
*
56+
* Documentation to handle manual migrations :
57+
* https://www.mongodb.com/docs/atlas/device-sdks/sdk/kotlin/realm-database/schemas/change-an-object-model/
58+
*/
59+
private fun MigrationContext.keepDefaultValuesAfterSixthMigration() {
60+
if (oldRealm.schemaVersion() <= 6L) {
61+
enumerate(className = "Mailbox") { oldObject: DynamicRealmObject, newObject: DynamicMutableRealmObject? ->
62+
newObject?.apply {
63+
64+
// Add property with default value
65+
set(propertyName = "_isValidInLdap", value = true)
66+
67+
// Rename property without losing its previous value
68+
set(propertyName = "_isLocked", value = oldObject.getValue<Boolean>(fieldName = "isLocked"))
69+
70+
// Rename property without losing its previous value
71+
set(propertyName = "hasValidPassword", value = oldObject.getValue<Boolean>(fieldName = "isPasswordValid"))
72+
}
73+
}
74+
}
75+
}

app/src/main/java/com/infomaniak/mail/data/cache/mailboxContent/RefreshController.kt

+2-2
Original file line numberDiff line numberDiff line change
@@ -98,10 +98,10 @@ class RefreshController @Inject constructor(
9898

9999
val folder = FolderController.getFolder(folderId, realm)!!
100100

101-
// If the Mailbox is invalid (i.e. the mailbox is locked or its password is wrong),
101+
// If the Mailbox is not available (i.e. the mailbox is locked or its password is wrong),
102102
// we'll be denied permission to fetch it by the API, so we don't even try to do it.
103103
// We can leave safely.
104-
if (!mailbox.isValid) {
104+
if (!mailbox.isAvailable) {
105105
SentryLog.w("API", "Refresh threads: We left early because of a predictable denied access.")
106106
return emptySet<Thread>() to null
107107
}

app/src/main/java/com/infomaniak/mail/data/cache/mailboxInfo/MailboxController.kt

+6-5
Original file line numberDiff line numberDiff line change
@@ -152,8 +152,9 @@ class MailboxController @Inject constructor(
152152
//region Queries
153153
private fun checkHasUserId(userId: Int) = "${Mailbox::userId.name} == '$userId'"
154154

155-
private val isMailboxLocked = "${Mailbox::isLocked.name} == true"
156-
private val hasValidPassword = "${Mailbox::isPasswordValid.name} == true"
155+
private val isValidInLdap = "${Mailbox.isValidInLdapPropertyName} == true"
156+
private val isLocked = "${Mailbox.isLockedPropertyName} == true"
157+
private val hasValidPassword = "${Mailbox::hasValidPassword.name} == true"
157158

158159
private fun getMailboxesQuery(
159160
userId: Int? = null,
@@ -179,7 +180,7 @@ class MailboxController @Inject constructor(
179180
}
180181

181182
private fun getValidMailboxesQuery(userId: Int, realm: TypedRealm): RealmQuery<Mailbox> {
182-
return realm.query("${checkHasUserId(userId)} AND $hasValidPassword AND (NOT $isMailboxLocked)")
183+
return realm.query("${checkHasUserId(userId)} AND $isValidInLdap AND NOT $isLocked AND $hasValidPassword")
183184
}
184185

185186
private fun getMailboxesCountQuery(userId: Int, realm: TypedRealm): RealmScalarQuery<Long> {
@@ -196,11 +197,11 @@ class MailboxController @Inject constructor(
196197
}
197198

198199
private fun getInvalidPasswordMailboxesQuery(userId: Int, realm: TypedRealm): RealmQuery<Mailbox> {
199-
return realm.query("${checkHasUserId(userId)} AND NOT ($hasValidPassword OR $isMailboxLocked)")
200+
return realm.query("${checkHasUserId(userId)} AND NOT $hasValidPassword AND NOT $isLocked AND $isValidInLdap")
200201
}
201202

202203
private fun getLockedMailboxesQuery(userId: Int, realm: TypedRealm): RealmQuery<Mailbox> {
203-
return realm.query("${checkHasUserId(userId)} AND $isMailboxLocked")
204+
return realm.query("${checkHasUserId(userId)} AND ($isLocked OR NOT $isValidInLdap)")
204205
}
205206
//endregion
206207

app/src/main/java/com/infomaniak/mail/data/models/mailbox/Mailbox.kt

+12-4
Original file line numberDiff line numberDiff line change
@@ -54,12 +54,14 @@ class Mailbox : RealmObject {
5454
var linkId: Int = 0
5555
@SerialName("is_limited")
5656
var isLimited: Boolean = false
57-
@SerialName("is_password_valid")
58-
var isPasswordValid: Boolean = true
5957
@SerialName("is_primary")
6058
var isPrimary: Boolean = false
59+
@SerialName("is_valid")
60+
private var _isValidInLdap: Boolean = true
6161
@SerialName("is_locked")
62-
var isLocked: Boolean = false
62+
private var _isLocked: Boolean = false
63+
@SerialName("is_password_valid")
64+
var hasValidPassword: Boolean = true
6365
@SerialName("unseen_messages")
6466
var unreadCountRemote: Int = 0
6567
var aliases = realmListOf<String>()
@@ -99,7 +101,8 @@ class Mailbox : RealmObject {
99101
inline val notificationGroupId get() = uuid.hashCode()
100102
inline val notificationGroupKey get() = uuid
101103

102-
inline val isValid get() = isPasswordValid && !isLocked
104+
val isLocked get() = _isLocked || !_isValidInLdap
105+
inline val isAvailable get() = !isLocked && hasValidPassword
103106

104107
val unreadCountDisplay: UnreadDisplay
105108
get() = UnreadDisplay(
@@ -150,4 +153,9 @@ class Mailbox : RealmObject {
150153
addAll(featureFlags)
151154
}
152155
}
156+
157+
companion object {
158+
val isValidInLdapPropertyName get() = Mailbox::_isValidInLdap.name
159+
val isLockedPropertyName get() = Mailbox::_isLocked.name
160+
}
153161
}

app/src/main/java/com/infomaniak/mail/ui/MainViewModel.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -251,7 +251,7 @@ class MainViewModel @Inject constructor(
251251
mailboxId = AccountUtils.currentMailboxId,
252252
) ?: return null
253253

254-
if (mailbox.isLocked || !mailbox.isPasswordValid) {
254+
if (!mailbox.isAvailable) {
255255
switchToValidMailbox()
256256
return null
257257
}

app/src/main/java/com/infomaniak/mail/ui/login/LoginActivity.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ class LoginActivity : AppCompatActivity() {
121121
context.trackUserInfo("nbMailboxes", mailboxes.count())
122122
AccountUtils.addUser(user)
123123
mailboxController.updateMailboxes(mailboxes)
124-
return@let if (mailboxes.none { it.isValid }) MailboxErrorCode.NO_VALID_MAILBOX else user
124+
return@let if (mailboxes.none { it.isAvailable }) MailboxErrorCode.NO_VALID_MAILBOX else user
125125
} ?: run {
126126
getErrorResponse(RCore.string.serverError)
127127
}

app/src/main/java/com/infomaniak/mail/ui/main/InvalidPasswordViewModel.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ class InvalidPasswordViewModel @Inject constructor(
5353
fun updatePassword(password: String) = viewModelScope.launch(ioCoroutineContext) {
5454
val apiResponse = ApiRepository.updateMailboxPassword(mailbox.mailboxId, password)
5555
if (apiResponse.isSuccess()) {
56-
mailboxController.updateMailbox(mailboxObjectId) { it.isPasswordValid = true }
56+
mailboxController.updateMailbox(mailboxObjectId) { it.hasValidPassword = true }
5757
AccountUtils.switchToMailbox(mailbox.mailboxId)
5858
} else {
5959
updatePasswordResult.postValue(apiResponse.translateError())

app/src/main/java/com/infomaniak/mail/ui/main/menuDrawer/MailboxesAdapter.kt

+2-2
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ class MailboxesAdapter(
7676

7777
override fun getItemViewType(position: Int): Int = runCatchingRealm {
7878
return when {
79-
!mailboxes[position].isValid -> DisplayType.INVALID_MAILBOX.layout
79+
!mailboxes[position].isAvailable -> DisplayType.INVALID_MAILBOX.layout
8080
isInMenuDrawer -> DisplayType.MENU_DRAWER_MAILBOX.layout
8181
else -> DisplayType.SIMPLE_MAILBOX.layout
8282
}
@@ -127,7 +127,7 @@ class MailboxesAdapter(
127127

128128
itemStyle = if (isInMenuDrawer) SelectionStyle.MENU_DRAWER else SelectionStyle.OTHER
129129

130-
isPasswordOutdated = !mailbox.isPasswordValid
130+
isPasswordOutdated = !mailbox.hasValidPassword
131131
isMailboxLocked = mailbox.isLocked
132132
hasNoValidMailboxes = !hasValidMailboxes
133133

app/src/main/java/com/infomaniak/mail/ui/main/menuDrawer/MenuDrawerAdapter.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ class MenuDrawerAdapter @Inject constructor() : ListAdapter<Any, MenuDrawerViewH
168168
return@runCatchingRealm when (val item = currentList[position]) {
169169
ItemType.DIVIDER -> ItemType.DIVIDER.ordinal
170170
is MailboxesHeader -> ItemType.MAILBOXES_HEADER.ordinal
171-
is Mailbox -> if (item.isValid) ItemType.MAILBOX.ordinal else ItemType.INVALID_MAILBOX.ordinal
171+
is Mailbox -> if (item.isAvailable) ItemType.MAILBOX.ordinal else ItemType.INVALID_MAILBOX.ordinal
172172
ItemType.FOLDERS_HEADER -> ItemType.FOLDERS_HEADER.ordinal
173173
is Folder -> ItemType.FOLDER.ordinal
174174
ItemType.EMPTY_FOLDERS -> ItemType.EMPTY_FOLDERS.ordinal

app/src/main/java/com/infomaniak/mail/ui/main/menuDrawer/items/InvalidMailboxViewHolder.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ class InvalidMailboxViewHolder(
4141

4242
text = mailbox.email
4343
itemStyle = DecoratedItemView.SelectionStyle.MENU_DRAWER
44-
isPasswordOutdated = !mailbox.isPasswordValid
44+
isPasswordOutdated = !mailbox.hasValidPassword
4545
isMailboxLocked = mailbox.isLocked
4646
hasNoValidMailboxes = false
4747

app/src/main/java/com/infomaniak/mail/ui/main/settings/SettingsFragment.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ class SettingsFragment : Fragment() {
8181
private fun setupMailboxesAdapter() {
8282
val mailboxesAdapter = SettingsMailboxesAdapter { selectedMailbox ->
8383
with(selectedMailbox) {
84-
if (isValid) {
84+
if (isAvailable) {
8585
animatedNavigation(SettingsFragmentDirections.actionSettingsToMailboxSettings(objectId, email))
8686
} else {
8787
context?.showToast(R.string.errorMailboxLocked)

app/src/main/java/com/infomaniak/mail/ui/main/settings/SettingsMailboxesAdapter.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ class SettingsMailboxesAdapter(
4141
setTitle(mailbox.email)
4242

4343
setOnClickListener { onMailboxSelected(mailbox) }
44-
toggleMailboxBlockedState(!mailbox.isValid)
44+
toggleMailboxBlockedState(!mailbox.isAvailable)
4545
}
4646

4747
override fun getItemCount(): Int = mailboxes.count()

app/src/main/java/com/infomaniak/mail/utils/AccountUtils.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ object AccountUtils : CredentialManager() {
9393
Dispatchers.Main { context.launchNoMailboxActivity(currentUserId, shouldStartLoginActivity = true) }
9494
true
9595
}
96-
mailboxes.none { it.isValid } -> {
96+
mailboxes.none { it.isAvailable } -> {
9797
Dispatchers.Main { context.launchNoValidMailboxesActivity() }
9898
true
9999
}

0 commit comments

Comments
 (0)