Merge pull request #3479 from vector-im/feature/fga/account_data_rework

Feature/fga/account data rework
This commit is contained in:
Benoit Marty 2021-06-09 20:33:49 +02:00 committed by GitHub
commit f1f7347650
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
32 changed files with 276 additions and 141 deletions

View file

@ -24,7 +24,7 @@ import kotlinx.coroutines.rx2.rxSingle
import org.matrix.android.sdk.api.extensions.orFalse import org.matrix.android.sdk.api.extensions.orFalse
import org.matrix.android.sdk.api.query.QueryStringValue import org.matrix.android.sdk.api.query.QueryStringValue
import org.matrix.android.sdk.api.session.Session import org.matrix.android.sdk.api.session.Session
import org.matrix.android.sdk.api.session.accountdata.AccountDataEvent import org.matrix.android.sdk.api.session.accountdata.UserAccountDataEvent
import org.matrix.android.sdk.api.session.crypto.crosssigning.KEYBACKUP_SECRET_SSSS_NAME import org.matrix.android.sdk.api.session.crypto.crosssigning.KEYBACKUP_SECRET_SSSS_NAME
import org.matrix.android.sdk.api.session.crypto.crosssigning.MASTER_KEY_SSSS_NAME import org.matrix.android.sdk.api.session.crypto.crosssigning.MASTER_KEY_SSSS_NAME
import org.matrix.android.sdk.api.session.crypto.crosssigning.MXCrossSigningInfo import org.matrix.android.sdk.api.session.crypto.crosssigning.MXCrossSigningInfo
@ -35,6 +35,7 @@ import org.matrix.android.sdk.api.session.group.model.GroupSummary
import org.matrix.android.sdk.api.session.identity.ThreePid import org.matrix.android.sdk.api.session.identity.ThreePid
import org.matrix.android.sdk.api.session.pushers.Pusher import org.matrix.android.sdk.api.session.pushers.Pusher
import org.matrix.android.sdk.api.session.room.RoomSummaryQueryParams import org.matrix.android.sdk.api.session.room.RoomSummaryQueryParams
import org.matrix.android.sdk.api.session.room.accountdata.RoomAccountDataEvent
import org.matrix.android.sdk.api.session.room.members.ChangeMembershipState import org.matrix.android.sdk.api.session.room.members.ChangeMembershipState
import org.matrix.android.sdk.api.session.room.model.RoomMemberSummary import org.matrix.android.sdk.api.session.room.model.RoomMemberSummary
import org.matrix.android.sdk.api.session.room.model.RoomSummary import org.matrix.android.sdk.api.session.room.model.RoomSummary
@ -177,10 +178,17 @@ class RxSession(private val session: Session) {
} }
} }
fun liveUserAccountData(types: Set<String>): Observable<List<AccountDataEvent>> { fun liveUserAccountData(types: Set<String>): Observable<List<UserAccountDataEvent>> {
return session.userAccountDataService().getLiveAccountDataEvents(types).asObservable() return session.accountDataService().getLiveUserAccountDataEvents(types).asObservable()
.startWithCallable { .startWithCallable {
session.userAccountDataService().getAccountDataEvents(types) session.accountDataService().getUserAccountDataEvents(types)
}
}
fun liveRoomAccountData(types: Set<String>): Observable<List<RoomAccountDataEvent>> {
return session.accountDataService().getLiveRoomAccountDataEvents(types).asObservable()
.startWithCallable {
session.accountDataService().getRoomAccountDataEvents(types)
} }
} }
@ -201,7 +209,7 @@ class RxSession(private val session: Session) {
} }
fun liveSecretSynchronisationInfo(): Observable<SecretsSynchronisationInfo> { fun liveSecretSynchronisationInfo(): Observable<SecretsSynchronisationInfo> {
return Observable.combineLatest<List<AccountDataEvent>, Optional<MXCrossSigningInfo>, Optional<PrivateKeysInfo>, SecretsSynchronisationInfo>( return Observable.combineLatest<List<UserAccountDataEvent>, Optional<MXCrossSigningInfo>, Optional<PrivateKeysInfo>, SecretsSynchronisationInfo>(
liveUserAccountData(setOf(MASTER_KEY_SSSS_NAME, USER_SIGNING_KEY_SSSS_NAME, SELF_SIGNING_KEY_SSSS_NAME, KEYBACKUP_SECRET_SSSS_NAME)), liveUserAccountData(setOf(MASTER_KEY_SSSS_NAME, USER_SIGNING_KEY_SSSS_NAME, SELF_SIGNING_KEY_SSSS_NAME, KEYBACKUP_SECRET_SSSS_NAME)),
liveCrossSigningInfo(session.myUserId), liveCrossSigningInfo(session.myUserId),
liveCrossSigningPrivateKeys(), liveCrossSigningPrivateKeys(),

View file

@ -33,7 +33,7 @@ import org.matrix.android.sdk.common.TestConstants
import org.matrix.android.sdk.internal.crypto.SSSS_ALGORITHM_AES_HMAC_SHA2 import org.matrix.android.sdk.internal.crypto.SSSS_ALGORITHM_AES_HMAC_SHA2
import org.matrix.android.sdk.internal.crypto.crosssigning.toBase64NoPadding import org.matrix.android.sdk.internal.crypto.crosssigning.toBase64NoPadding
import org.matrix.android.sdk.internal.crypto.secrets.DefaultSharedSecretStorageService import org.matrix.android.sdk.internal.crypto.secrets.DefaultSharedSecretStorageService
import org.matrix.android.sdk.api.session.accountdata.AccountDataEvent import org.matrix.android.sdk.api.session.accountdata.UserAccountDataEvent
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@ -73,12 +73,12 @@ class QuadSTests : InstrumentedTest {
// Assert Account data is updated // Assert Account data is updated
val accountDataLock = CountDownLatch(1) val accountDataLock = CountDownLatch(1)
var accountData: AccountDataEvent? = null var accountData: UserAccountDataEvent? = null
val liveAccountData = runBlocking(Dispatchers.Main) { val liveAccountData = runBlocking(Dispatchers.Main) {
aliceSession.userAccountDataService().getLiveAccountDataEvent("${DefaultSharedSecretStorageService.KEY_ID_BASE}.$TEST_KEY_ID") aliceSession.accountDataService().getLiveUserAccountDataEvent("${DefaultSharedSecretStorageService.KEY_ID_BASE}.$TEST_KEY_ID")
} }
val accountDataObserver = Observer<Optional<AccountDataEvent>?> { t -> val accountDataObserver = Observer<Optional<UserAccountDataEvent>?> { t ->
if (t?.getOrNull()?.type == "${DefaultSharedSecretStorageService.KEY_ID_BASE}.$TEST_KEY_ID") { if (t?.getOrNull()?.type == "${DefaultSharedSecretStorageService.KEY_ID_BASE}.$TEST_KEY_ID") {
accountData = t.getOrNull() accountData = t.getOrNull()
accountDataLock.countDown() accountDataLock.countDown()
@ -100,13 +100,13 @@ class QuadSTests : InstrumentedTest {
quadS.setDefaultKey(TEST_KEY_ID) quadS.setDefaultKey(TEST_KEY_ID)
} }
var defaultKeyAccountData: AccountDataEvent? = null var defaultKeyAccountData: UserAccountDataEvent? = null
val defaultDataLock = CountDownLatch(1) val defaultDataLock = CountDownLatch(1)
val liveDefAccountData = runBlocking(Dispatchers.Main) { val liveDefAccountData = runBlocking(Dispatchers.Main) {
aliceSession.userAccountDataService().getLiveAccountDataEvent(DefaultSharedSecretStorageService.DEFAULT_KEY_ID) aliceSession.accountDataService().getLiveUserAccountDataEvent(DefaultSharedSecretStorageService.DEFAULT_KEY_ID)
} }
val accountDefDataObserver = Observer<Optional<AccountDataEvent>?> { t -> val accountDefDataObserver = Observer<Optional<UserAccountDataEvent>?> { t ->
if (t?.getOrNull()?.type == DefaultSharedSecretStorageService.DEFAULT_KEY_ID) { if (t?.getOrNull()?.type == DefaultSharedSecretStorageService.DEFAULT_KEY_ID) {
defaultKeyAccountData = t.getOrNull()!! defaultKeyAccountData = t.getOrNull()!!
defaultDataLock.countDown() defaultDataLock.countDown()
@ -206,7 +206,7 @@ class QuadSTests : InstrumentedTest {
) )
} }
val accountDataEvent = aliceSession.userAccountDataService().getAccountDataEvent("my.secret") val accountDataEvent = aliceSession.accountDataService().getUserAccountDataEvent("my.secret")
val encryptedContent = accountDataEvent?.content?.get("encrypted") as? Map<*, *> val encryptedContent = accountDataEvent?.content?.get("encrypted") as? Map<*, *>
assertEquals("Content should contains two encryptions", 2, encryptedContent?.keys?.size ?: 0) assertEquals("Content should contains two encryptions", 2, encryptedContent?.keys?.size ?: 0)
@ -275,14 +275,14 @@ class QuadSTests : InstrumentedTest {
mTestHelper.signOutAndClose(aliceSession) mTestHelper.signOutAndClose(aliceSession)
} }
private fun assertAccountData(session: Session, type: String): AccountDataEvent { private fun assertAccountData(session: Session, type: String): UserAccountDataEvent {
val accountDataLock = CountDownLatch(1) val accountDataLock = CountDownLatch(1)
var accountData: AccountDataEvent? = null var accountData: UserAccountDataEvent? = null
val liveAccountData = runBlocking(Dispatchers.Main) { val liveAccountData = runBlocking(Dispatchers.Main) {
session.userAccountDataService().getLiveAccountDataEvent(type) session.accountDataService().getLiveUserAccountDataEvent(type)
} }
val accountDataObserver = Observer<Optional<AccountDataEvent>?> { t -> val accountDataObserver = Observer<Optional<UserAccountDataEvent>?> { t ->
if (t?.getOrNull()?.type == type) { if (t?.getOrNull()?.type == type) {
accountData = t.getOrNull() accountData = t.getOrNull()
accountDataLock.countDown() accountDataLock.countDown()

View file

@ -24,7 +24,7 @@ import org.matrix.android.sdk.api.failure.GlobalError
import org.matrix.android.sdk.api.federation.FederationService import org.matrix.android.sdk.api.federation.FederationService
import org.matrix.android.sdk.api.pushrules.PushRuleService import org.matrix.android.sdk.api.pushrules.PushRuleService
import org.matrix.android.sdk.api.session.account.AccountService import org.matrix.android.sdk.api.session.account.AccountService
import org.matrix.android.sdk.api.session.accountdata.AccountDataService import org.matrix.android.sdk.api.session.accountdata.SessionAccountDataService
import org.matrix.android.sdk.api.session.cache.CacheService import org.matrix.android.sdk.api.session.cache.CacheService
import org.matrix.android.sdk.api.session.call.CallSignalingService import org.matrix.android.sdk.api.session.call.CallSignalingService
import org.matrix.android.sdk.api.session.content.ContentUploadStateTracker import org.matrix.android.sdk.api.session.content.ContentUploadStateTracker
@ -239,9 +239,9 @@ interface Session :
fun openIdService(): OpenIdService fun openIdService(): OpenIdService
/** /**
* Returns the user account data service associated with the session * Returns the account data service associated with the session
*/ */
fun userAccountDataService(): AccountDataService fun accountDataService(): SessionAccountDataService
/** /**
* Add a listener to the session. * Add a listener to the session.

View file

@ -0,0 +1,66 @@
/*
* Copyright 2020 The Matrix.org Foundation C.I.C.
*
* 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 org.matrix.android.sdk.api.session.accountdata
import androidx.lifecycle.LiveData
import org.matrix.android.sdk.api.session.events.model.Content
import org.matrix.android.sdk.api.session.room.accountdata.RoomAccountDataEvent
import org.matrix.android.sdk.api.util.Optional
/**
* This service is attached globally to the session.
*/
interface SessionAccountDataService {
/**
* Retrieve the account data with the provided type or null if not found
*/
fun getUserAccountDataEvent(type: String): UserAccountDataEvent?
/**
* Observe the account data with the provided type
*/
fun getLiveUserAccountDataEvent(type: String): LiveData<Optional<UserAccountDataEvent>>
/**
* Retrieve the account data with the provided types. The return list can have a different size that
* the size of the types set, because some AccountData may not exist.
* If an empty set is provided, all the AccountData are retrieved
*/
fun getUserAccountDataEvents(types: Set<String>): List<UserAccountDataEvent>
/**
* Observe the account data with the provided types. If an empty set is provided, all the AccountData are observed
*/
fun getLiveUserAccountDataEvents(types: Set<String>): LiveData<List<UserAccountDataEvent>>
/**
* Retrieve the room account data with the provided types. The return list can have a different size that
* the size of the types set, because some AccountData may not exist.
* If an empty set is provided, all the room AccountData are retrieved
*/
fun getRoomAccountDataEvents(types: Set<String>): List<RoomAccountDataEvent>
/**
* Observe the room account data with the provided types. If an empty set is provided, AccountData of every room are observed
*/
fun getLiveRoomAccountDataEvents(types: Set<String>): LiveData<List<RoomAccountDataEvent>>
/**
* Update the account data with the provided type and the provided account data content
*/
suspend fun updateUserAccountData(type: String, content: Content)
}

View file

@ -22,10 +22,10 @@ import org.matrix.android.sdk.api.session.events.model.Content
/** /**
* This is a simplified Event with just a type and a content. * This is a simplified Event with just a type and a content.
* Currently used types are defined in [UserAccountDataTypes]. * Currently used types are defined in [UserAccountDataTypes]
*/ */
@JsonClass(generateAdapter = true) @JsonClass(generateAdapter = true)
data class AccountDataEvent( data class UserAccountDataEvent(
@Json(name = "type") val type: String, @Json(name = "type") val type: String,
@Json(name = "content") val content: Content @Json(name = "content") val content: Content
) )

View file

@ -17,7 +17,7 @@
package org.matrix.android.sdk.api.session.room package org.matrix.android.sdk.api.session.room
import androidx.lifecycle.LiveData import androidx.lifecycle.LiveData
import org.matrix.android.sdk.api.session.accountdata.AccountDataService import org.matrix.android.sdk.api.session.room.accountdata.RoomAccountDataService
import org.matrix.android.sdk.api.session.room.alias.AliasService import org.matrix.android.sdk.api.session.room.alias.AliasService
import org.matrix.android.sdk.api.session.room.call.RoomCallService import org.matrix.android.sdk.api.session.room.call.RoomCallService
import org.matrix.android.sdk.api.session.room.crypto.RoomCryptoService import org.matrix.android.sdk.api.session.room.crypto.RoomCryptoService
@ -57,7 +57,7 @@ interface Room :
RelationService, RelationService,
RoomCryptoService, RoomCryptoService,
RoomPushRuleService, RoomPushRuleService,
AccountDataService { RoomAccountDataService {
/** /**
* The roomId of this room * The roomId of this room

View file

@ -0,0 +1,29 @@
/*
* Copyright 2020 The Matrix.org Foundation C.I.C.
*
* 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 org.matrix.android.sdk.api.session.room.accountdata
import org.matrix.android.sdk.api.session.events.model.Content
/**
* This is a simplified Event with just a roomId, a type and a content.
* Currently used types are defined in [RoomAccountDataTypes].
*/
data class RoomAccountDataEvent(
val roomId: String,
val type: String,
val content: Content
)

View file

@ -14,37 +14,37 @@
* limitations under the License. * limitations under the License.
*/ */
package org.matrix.android.sdk.api.session.accountdata package org.matrix.android.sdk.api.session.room.accountdata
import androidx.lifecycle.LiveData import androidx.lifecycle.LiveData
import org.matrix.android.sdk.api.session.events.model.Content import org.matrix.android.sdk.api.session.events.model.Content
import org.matrix.android.sdk.api.util.Optional import org.matrix.android.sdk.api.util.Optional
/** /**
* This service can be attached globally to the session so it represents user data or attached to a single room. * This service is attached to a single room.
*/ */
interface AccountDataService { interface RoomAccountDataService {
/** /**
* Retrieve the account data with the provided type or null if not found * Retrieve the account data with the provided type or null if not found
*/ */
fun getAccountDataEvent(type: String): AccountDataEvent? fun getAccountDataEvent(type: String): RoomAccountDataEvent?
/** /**
* Observe the account data with the provided type * Observe the account data with the provided type
*/ */
fun getLiveAccountDataEvent(type: String): LiveData<Optional<AccountDataEvent>> fun getLiveAccountDataEvent(type: String): LiveData<Optional<RoomAccountDataEvent>>
/** /**
* Retrieve the account data with the provided types. The return list can have a different size that * Retrieve the account data with the provided types. The return list can have a different size that
* the size of the types set, because some AccountData may not exist. * the size of the types set, because some AccountData may not exist.
* If an empty set is provided, all the AccountData are retrieved * If an empty set is provided, all the AccountData are retrieved
*/ */
fun getAccountDataEvents(types: Set<String>): List<AccountDataEvent> fun getAccountDataEvents(types: Set<String>): List<RoomAccountDataEvent>
/** /**
* Observe the account data with the provided types. If an empty set is provided, all the AccountData are observed * Observe the account data with the provided types. If an empty set is provided, all the AccountData are observed
*/ */
fun getLiveAccountDataEvents(types: Set<String>): LiveData<List<AccountDataEvent>> fun getLiveAccountDataEvents(types: Set<String>): LiveData<List<RoomAccountDataEvent>>
/** /**
* Update the account data with the provided type and the provided account data content * Update the account data with the provided type and the provided account data content

View file

@ -18,7 +18,7 @@ package org.matrix.android.sdk.internal.crypto.secrets
import org.matrix.android.sdk.api.extensions.orFalse import org.matrix.android.sdk.api.extensions.orFalse
import org.matrix.android.sdk.api.listeners.ProgressListener import org.matrix.android.sdk.api.listeners.ProgressListener
import org.matrix.android.sdk.api.session.accountdata.AccountDataService import org.matrix.android.sdk.api.session.accountdata.SessionAccountDataService
import org.matrix.android.sdk.api.session.events.model.toContent import org.matrix.android.sdk.api.session.events.model.toContent
import org.matrix.android.sdk.api.session.securestorage.EncryptedSecretContent import org.matrix.android.sdk.api.session.securestorage.EncryptedSecretContent
import org.matrix.android.sdk.api.session.securestorage.IntegrityResult import org.matrix.android.sdk.api.session.securestorage.IntegrityResult
@ -56,7 +56,7 @@ import kotlin.experimental.and
internal class DefaultSharedSecretStorageService @Inject constructor( internal class DefaultSharedSecretStorageService @Inject constructor(
@UserId private val userId: String, @UserId private val userId: String,
private val accountDataService: AccountDataService, private val accountDataService: SessionAccountDataService,
private val outgoingGossipingRequestManager: OutgoingGossipingRequestManager, private val outgoingGossipingRequestManager: OutgoingGossipingRequestManager,
private val coroutineDispatchers: MatrixCoroutineDispatchers, private val coroutineDispatchers: MatrixCoroutineDispatchers,
private val cryptoCoroutineScope: CoroutineScope private val cryptoCoroutineScope: CoroutineScope
@ -84,7 +84,7 @@ internal class DefaultSharedSecretStorageService @Inject constructor(
) )
} ?: storageKeyContent } ?: storageKeyContent
accountDataService.updateAccountData("$KEY_ID_BASE.$keyId", signedContent.toContent()) accountDataService.updateUserAccountData("$KEY_ID_BASE.$keyId", signedContent.toContent())
SsssKeyCreationInfo( SsssKeyCreationInfo(
keyId = keyId, keyId = keyId,
content = storageKeyContent, content = storageKeyContent,
@ -113,7 +113,7 @@ internal class DefaultSharedSecretStorageService @Inject constructor(
) )
} ?: storageKeyContent } ?: storageKeyContent
accountDataService.updateAccountData( accountDataService.updateUserAccountData(
"$KEY_ID_BASE.$keyId", "$KEY_ID_BASE.$keyId",
signedContent.toContent() signedContent.toContent()
) )
@ -127,11 +127,11 @@ internal class DefaultSharedSecretStorageService @Inject constructor(
} }
override fun hasKey(keyId: String): Boolean { override fun hasKey(keyId: String): Boolean {
return accountDataService.getAccountDataEvent("$KEY_ID_BASE.$keyId") != null return accountDataService.getUserAccountDataEvent("$KEY_ID_BASE.$keyId") != null
} }
override fun getKey(keyId: String): KeyInfoResult { override fun getKey(keyId: String): KeyInfoResult {
val accountData = accountDataService.getAccountDataEvent("$KEY_ID_BASE.$keyId") val accountData = accountDataService.getUserAccountDataEvent("$KEY_ID_BASE.$keyId")
?: return KeyInfoResult.Error(SharedSecretStorageError.UnknownKey(keyId)) ?: return KeyInfoResult.Error(SharedSecretStorageError.UnknownKey(keyId))
return SecretStorageKeyContent.fromJson(accountData.content)?.let { return SecretStorageKeyContent.fromJson(accountData.content)?.let {
KeyInfoResult.Success( KeyInfoResult.Success(
@ -143,14 +143,14 @@ internal class DefaultSharedSecretStorageService @Inject constructor(
override suspend fun setDefaultKey(keyId: String) { override suspend fun setDefaultKey(keyId: String) {
val existingKey = getKey(keyId) val existingKey = getKey(keyId)
if (existingKey is KeyInfoResult.Success) { if (existingKey is KeyInfoResult.Success) {
accountDataService.updateAccountData(DEFAULT_KEY_ID, mapOf("key" to keyId)) accountDataService.updateUserAccountData(DEFAULT_KEY_ID, mapOf("key" to keyId))
} else { } else {
throw SharedSecretStorageError.UnknownKey(keyId) throw SharedSecretStorageError.UnknownKey(keyId)
} }
} }
override fun getDefaultKey(): KeyInfoResult { override fun getDefaultKey(): KeyInfoResult {
val accountData = accountDataService.getAccountDataEvent(DEFAULT_KEY_ID) val accountData = accountDataService.getUserAccountDataEvent(DEFAULT_KEY_ID)
?: return KeyInfoResult.Error(SharedSecretStorageError.UnknownKey(DEFAULT_KEY_ID)) ?: return KeyInfoResult.Error(SharedSecretStorageError.UnknownKey(DEFAULT_KEY_ID))
val keyId = accountData.content["key"] as? String val keyId = accountData.content["key"] as? String
?: return KeyInfoResult.Error(SharedSecretStorageError.UnknownKey(DEFAULT_KEY_ID)) ?: return KeyInfoResult.Error(SharedSecretStorageError.UnknownKey(DEFAULT_KEY_ID))
@ -178,7 +178,7 @@ internal class DefaultSharedSecretStorageService @Inject constructor(
} }
} }
accountDataService.updateAccountData( accountDataService.updateUserAccountData(
type = name, type = name,
content = mapOf("encrypted" to encryptedContents) content = mapOf("encrypted" to encryptedContents)
) )
@ -288,7 +288,7 @@ internal class DefaultSharedSecretStorageService @Inject constructor(
} }
override fun getAlgorithmsForSecret(name: String): List<KeyInfoResult> { override fun getAlgorithmsForSecret(name: String): List<KeyInfoResult> {
val accountData = accountDataService.getAccountDataEvent(name) val accountData = accountDataService.getUserAccountDataEvent(name)
?: return listOf(KeyInfoResult.Error(SharedSecretStorageError.UnknownSecret(name))) ?: return listOf(KeyInfoResult.Error(SharedSecretStorageError.UnknownSecret(name)))
val encryptedContent = accountData.content[ENCRYPTED] as? Map<*, *> val encryptedContent = accountData.content[ENCRYPTED] as? Map<*, *>
?: return listOf(KeyInfoResult.Error(SharedSecretStorageError.SecretNotEncrypted(name))) ?: return listOf(KeyInfoResult.Error(SharedSecretStorageError.SecretNotEncrypted(name)))
@ -303,7 +303,7 @@ internal class DefaultSharedSecretStorageService @Inject constructor(
} }
override suspend fun getSecret(name: String, keyId: String?, secretKey: SsssKeySpec): String { override suspend fun getSecret(name: String, keyId: String?, secretKey: SsssKeySpec): String {
val accountData = accountDataService.getAccountDataEvent(name) ?: throw SharedSecretStorageError.UnknownSecret(name) val accountData = accountDataService.getUserAccountDataEvent(name) ?: throw SharedSecretStorageError.UnknownSecret(name)
val encryptedContent = accountData.content[ENCRYPTED] as? Map<*, *> ?: throw SharedSecretStorageError.SecretNotEncrypted(name) val encryptedContent = accountData.content[ENCRYPTED] as? Map<*, *> ?: throw SharedSecretStorageError.SecretNotEncrypted(name)
val key = keyId?.let { getKey(it) } as? KeyInfoResult.Success ?: getDefaultKey() as? KeyInfoResult.Success val key = keyId?.let { getKey(it) } as? KeyInfoResult.Success ?: getDefaultKey() as? KeyInfoResult.Success
?: throw SharedSecretStorageError.UnknownKey(name) ?: throw SharedSecretStorageError.UnknownKey(name)
@ -368,7 +368,7 @@ internal class DefaultSharedSecretStorageService @Inject constructor(
} }
secretNames.forEach { secretName -> secretNames.forEach { secretName ->
val secretEvent = accountDataService.getAccountDataEvent(secretName) val secretEvent = accountDataService.getUserAccountDataEvent(secretName)
?: return IntegrityResult.Error(SharedSecretStorageError.UnknownSecret(secretName)) ?: return IntegrityResult.Error(SharedSecretStorageError.UnknownSecret(secretName))
if ((secretEvent.content["encrypted"] as? Map<*, *>)?.get(keyInfo.id) == null) { if ((secretEvent.content["encrypted"] as? Map<*, *>)?.get(keyInfo.id) == null) {
return IntegrityResult.Error(SharedSecretStorageError.SecretNotEncryptedWithKey(secretName, keyInfo.id)) return IntegrityResult.Error(SharedSecretStorageError.SecretNotEncryptedWithKey(secretName, keyInfo.id))

View file

@ -17,7 +17,8 @@
package org.matrix.android.sdk.internal.database.mapper package org.matrix.android.sdk.internal.database.mapper
import com.squareup.moshi.Moshi import com.squareup.moshi.Moshi
import org.matrix.android.sdk.api.session.accountdata.AccountDataEvent import org.matrix.android.sdk.api.session.accountdata.UserAccountDataEvent
import org.matrix.android.sdk.api.session.room.accountdata.RoomAccountDataEvent
import org.matrix.android.sdk.api.util.JSON_DICT_PARAMETERIZED_TYPE import org.matrix.android.sdk.api.util.JSON_DICT_PARAMETERIZED_TYPE
import org.matrix.android.sdk.internal.database.model.RoomAccountDataEntity import org.matrix.android.sdk.internal.database.model.RoomAccountDataEntity
import org.matrix.android.sdk.internal.database.model.UserAccountDataEntity import org.matrix.android.sdk.internal.database.model.UserAccountDataEntity
@ -27,15 +28,16 @@ internal class AccountDataMapper @Inject constructor(moshi: Moshi) {
private val adapter = moshi.adapter<Map<String, Any>>(JSON_DICT_PARAMETERIZED_TYPE) private val adapter = moshi.adapter<Map<String, Any>>(JSON_DICT_PARAMETERIZED_TYPE)
fun map(entity: UserAccountDataEntity): AccountDataEvent { fun map(entity: UserAccountDataEntity): UserAccountDataEvent {
return AccountDataEvent( return UserAccountDataEvent(
type = entity.type ?: "", type = entity.type ?: "",
content = entity.contentStr?.let { adapter.fromJson(it) }.orEmpty() content = entity.contentStr?.let { adapter.fromJson(it) }.orEmpty()
) )
} }
fun map(entity: RoomAccountDataEntity): AccountDataEvent { fun map(roomId: String, entity: RoomAccountDataEntity): RoomAccountDataEvent {
return AccountDataEvent( return RoomAccountDataEvent(
roomId = roomId,
type = entity.type ?: "", type = entity.type ?: "",
content = entity.contentStr?.let { adapter.fromJson(it) }.orEmpty() content = entity.contentStr?.let { adapter.fromJson(it) }.orEmpty()
) )

View file

@ -29,7 +29,7 @@ import org.matrix.android.sdk.api.pushrules.PushRuleService
import org.matrix.android.sdk.api.session.Session import org.matrix.android.sdk.api.session.Session
import org.matrix.android.sdk.api.session.SessionLifecycleObserver import org.matrix.android.sdk.api.session.SessionLifecycleObserver
import org.matrix.android.sdk.api.session.account.AccountService import org.matrix.android.sdk.api.session.account.AccountService
import org.matrix.android.sdk.api.session.accountdata.AccountDataService import org.matrix.android.sdk.api.session.accountdata.SessionAccountDataService
import org.matrix.android.sdk.api.session.cache.CacheService import org.matrix.android.sdk.api.session.cache.CacheService
import org.matrix.android.sdk.api.session.call.CallSignalingService import org.matrix.android.sdk.api.session.call.CallSignalingService
import org.matrix.android.sdk.api.session.content.ContentUploadStateTracker import org.matrix.android.sdk.api.session.content.ContentUploadStateTracker
@ -74,7 +74,6 @@ import org.matrix.android.sdk.internal.session.identity.DefaultIdentityService
import org.matrix.android.sdk.internal.session.sync.SyncTokenStore import org.matrix.android.sdk.internal.session.sync.SyncTokenStore
import org.matrix.android.sdk.internal.session.sync.job.SyncThread import org.matrix.android.sdk.internal.session.sync.job.SyncThread
import org.matrix.android.sdk.internal.session.sync.job.SyncWorker import org.matrix.android.sdk.internal.session.sync.job.SyncWorker
import org.matrix.android.sdk.internal.session.user.accountdata.UserAccountDataService
import org.matrix.android.sdk.internal.util.createUIHandler import org.matrix.android.sdk.internal.util.createUIHandler
import timber.log.Timber import timber.log.Timber
import javax.inject.Inject import javax.inject.Inject
@ -118,7 +117,7 @@ internal class DefaultSession @Inject constructor(
private val contentDownloadStateTracker: ContentDownloadStateTracker, private val contentDownloadStateTracker: ContentDownloadStateTracker,
private val initialSyncProgressService: Lazy<InitialSyncProgressService>, private val initialSyncProgressService: Lazy<InitialSyncProgressService>,
private val homeServerCapabilitiesService: Lazy<HomeServerCapabilitiesService>, private val homeServerCapabilitiesService: Lazy<HomeServerCapabilitiesService>,
private val accountDataService: Lazy<UserAccountDataService>, private val accountDataService: Lazy<SessionAccountDataService>,
private val _sharedSecretStorageService: Lazy<SharedSecretStorageService>, private val _sharedSecretStorageService: Lazy<SharedSecretStorageService>,
private val accountService: Lazy<AccountService>, private val accountService: Lazy<AccountService>,
private val eventService: Lazy<EventService>, private val eventService: Lazy<EventService>,
@ -293,7 +292,7 @@ internal class DefaultSession @Inject constructor(
override fun openIdService(): OpenIdService = openIdService.get() override fun openIdService(): OpenIdService = openIdService.get()
override fun userAccountDataService(): AccountDataService = accountDataService.get() override fun accountDataService(): SessionAccountDataService = accountDataService.get()
override fun getOkHttpClient(): OkHttpClient { override fun getOkHttpClient(): OkHttpClient {
return unauthenticatedWithCertificateOkHttpClient.get() return unauthenticatedWithCertificateOkHttpClient.get()

View file

@ -34,7 +34,7 @@ import org.matrix.android.sdk.api.auth.data.sessionId
import org.matrix.android.sdk.api.crypto.MXCryptoConfig import org.matrix.android.sdk.api.crypto.MXCryptoConfig
import org.matrix.android.sdk.api.session.Session import org.matrix.android.sdk.api.session.Session
import org.matrix.android.sdk.api.session.SessionLifecycleObserver import org.matrix.android.sdk.api.session.SessionLifecycleObserver
import org.matrix.android.sdk.api.session.accountdata.AccountDataService import org.matrix.android.sdk.api.session.accountdata.SessionAccountDataService
import org.matrix.android.sdk.api.session.events.EventService import org.matrix.android.sdk.api.session.events.EventService
import org.matrix.android.sdk.api.session.homeserver.HomeServerCapabilitiesService import org.matrix.android.sdk.api.session.homeserver.HomeServerCapabilitiesService
import org.matrix.android.sdk.api.session.initsync.InitialSyncProgressService import org.matrix.android.sdk.api.session.initsync.InitialSyncProgressService
@ -93,7 +93,7 @@ import org.matrix.android.sdk.internal.session.room.send.queue.EventSenderProces
import org.matrix.android.sdk.internal.session.room.tombstone.RoomTombstoneEventProcessor import org.matrix.android.sdk.internal.session.room.tombstone.RoomTombstoneEventProcessor
import org.matrix.android.sdk.internal.session.securestorage.DefaultSecureStorageService import org.matrix.android.sdk.internal.session.securestorage.DefaultSecureStorageService
import org.matrix.android.sdk.internal.session.typing.DefaultTypingUsersTracker import org.matrix.android.sdk.internal.session.typing.DefaultTypingUsersTracker
import org.matrix.android.sdk.internal.session.user.accountdata.UserAccountDataService import org.matrix.android.sdk.internal.session.user.accountdata.DefaultSessionAccountDataService
import org.matrix.android.sdk.internal.session.widgets.DefaultWidgetURLFormatter import org.matrix.android.sdk.internal.session.widgets.DefaultWidgetURLFormatter
import org.matrix.android.sdk.internal.util.md5 import org.matrix.android.sdk.internal.util.md5
import retrofit2.Retrofit import retrofit2.Retrofit
@ -364,7 +364,7 @@ internal abstract class SessionModule {
abstract fun bindHomeServerCapabilitiesService(service: DefaultHomeServerCapabilitiesService): HomeServerCapabilitiesService abstract fun bindHomeServerCapabilitiesService(service: DefaultHomeServerCapabilitiesService): HomeServerCapabilitiesService
@Binds @Binds
abstract fun bindAccountDataService(service: UserAccountDataService): AccountDataService abstract fun bindSessionAccountDataService(service: DefaultSessionAccountDataService): SessionAccountDataService
@Binds @Binds
abstract fun bindEventService(service: DefaultEventService): EventService abstract fun bindEventService(service: DefaultEventService): EventService

View file

@ -33,7 +33,7 @@ import org.matrix.android.sdk.internal.extensions.observeNotNull
import org.matrix.android.sdk.api.session.SessionLifecycleObserver import org.matrix.android.sdk.api.session.SessionLifecycleObserver
import org.matrix.android.sdk.internal.session.SessionScope import org.matrix.android.sdk.internal.session.SessionScope
import org.matrix.android.sdk.api.session.accountdata.UserAccountDataTypes import org.matrix.android.sdk.api.session.accountdata.UserAccountDataTypes
import org.matrix.android.sdk.api.session.accountdata.AccountDataEvent import org.matrix.android.sdk.api.session.accountdata.UserAccountDataEvent
import org.matrix.android.sdk.internal.session.user.accountdata.UserAccountDataDataSource import org.matrix.android.sdk.internal.session.user.accountdata.UserAccountDataDataSource
import org.matrix.android.sdk.internal.session.user.accountdata.UpdateUserAccountDataTask import org.matrix.android.sdk.internal.session.user.accountdata.UpdateUserAccountDataTask
import org.matrix.android.sdk.internal.session.widgets.helper.WidgetFactory import org.matrix.android.sdk.internal.session.widgets.helper.WidgetFactory
@ -240,7 +240,7 @@ internal class IntegrationManager @Inject constructor(matrixConfiguration: Matri
) )
} }
private fun AccountDataEvent.asIntegrationManagerWidgetContent(): WidgetContent? { private fun UserAccountDataEvent.asIntegrationManagerWidgetContent(): WidgetContent? {
return extractWidgetSequence(widgetFactory) return extractWidgetSequence(widgetFactory)
.filter { .filter {
WidgetType.IntegrationManager == it.type WidgetType.IntegrationManager == it.type

View file

@ -17,10 +17,10 @@
package org.matrix.android.sdk.internal.session.room package org.matrix.android.sdk.internal.session.room
import androidx.lifecycle.LiveData import androidx.lifecycle.LiveData
import org.matrix.android.sdk.api.session.accountdata.AccountDataService
import org.matrix.android.sdk.api.session.crypto.CryptoService import org.matrix.android.sdk.api.session.crypto.CryptoService
import org.matrix.android.sdk.api.session.events.model.EventType import org.matrix.android.sdk.api.session.events.model.EventType
import org.matrix.android.sdk.api.session.room.Room import org.matrix.android.sdk.api.session.room.Room
import org.matrix.android.sdk.api.session.room.accountdata.RoomAccountDataService
import org.matrix.android.sdk.api.session.room.alias.AliasService import org.matrix.android.sdk.api.session.room.alias.AliasService
import org.matrix.android.sdk.api.session.room.call.RoomCallService import org.matrix.android.sdk.api.session.room.call.RoomCallService
import org.matrix.android.sdk.api.session.room.members.MembershipService import org.matrix.android.sdk.api.session.room.members.MembershipService
@ -42,7 +42,6 @@ import org.matrix.android.sdk.api.session.space.Space
import org.matrix.android.sdk.api.util.Optional import org.matrix.android.sdk.api.util.Optional
import org.matrix.android.sdk.internal.crypto.MXCRYPTO_ALGORITHM_MEGOLM import org.matrix.android.sdk.internal.crypto.MXCRYPTO_ALGORITHM_MEGOLM
import org.matrix.android.sdk.internal.session.permalinks.ViaParameterFinder import org.matrix.android.sdk.internal.session.permalinks.ViaParameterFinder
import org.matrix.android.sdk.internal.session.room.accountdata.RoomAccountDataService
import org.matrix.android.sdk.internal.session.room.state.SendStateTask import org.matrix.android.sdk.internal.session.room.state.SendStateTask
import org.matrix.android.sdk.internal.session.room.summary.RoomSummaryDataSource import org.matrix.android.sdk.internal.session.room.summary.RoomSummaryDataSource
import org.matrix.android.sdk.internal.session.search.SearchTask import org.matrix.android.sdk.internal.session.search.SearchTask
@ -86,7 +85,7 @@ internal class DefaultRoom(override val roomId: String,
RelationService by relationService, RelationService by relationService,
MembershipService by roomMembersService, MembershipService by roomMembersService,
RoomPushRuleService by roomPushRuleService, RoomPushRuleService by roomPushRuleService,
AccountDataService by roomAccountDataService { RoomAccountDataService by roomAccountDataService {
override fun getRoomSummaryLive(): LiveData<Optional<RoomSummary>> { override fun getRoomSummaryLive(): LiveData<Optional<RoomSummary>> {
return roomSummaryDataSource.getRoomSummaryLive(roomId) return roomSummaryDataSource.getRoomSummaryLive(roomId)

View file

@ -19,8 +19,8 @@ package org.matrix.android.sdk.internal.session.room
import org.matrix.android.sdk.api.session.crypto.CryptoService import org.matrix.android.sdk.api.session.crypto.CryptoService
import org.matrix.android.sdk.api.session.room.Room import org.matrix.android.sdk.api.session.room.Room
import org.matrix.android.sdk.internal.session.SessionScope import org.matrix.android.sdk.internal.session.SessionScope
import org.matrix.android.sdk.internal.session.room.accountdata.RoomAccountDataService
import org.matrix.android.sdk.internal.session.permalinks.ViaParameterFinder import org.matrix.android.sdk.internal.session.permalinks.ViaParameterFinder
import org.matrix.android.sdk.internal.session.room.accountdata.DefaultRoomAccountDataService
import org.matrix.android.sdk.internal.session.room.alias.DefaultAliasService import org.matrix.android.sdk.internal.session.room.alias.DefaultAliasService
import org.matrix.android.sdk.internal.session.room.call.DefaultRoomCallService import org.matrix.android.sdk.internal.session.room.call.DefaultRoomCallService
import org.matrix.android.sdk.internal.session.room.draft.DefaultDraftService import org.matrix.android.sdk.internal.session.room.draft.DefaultDraftService
@ -61,7 +61,7 @@ internal class DefaultRoomFactory @Inject constructor(private val cryptoService:
private val relationServiceFactory: DefaultRelationService.Factory, private val relationServiceFactory: DefaultRelationService.Factory,
private val membershipServiceFactory: DefaultMembershipService.Factory, private val membershipServiceFactory: DefaultMembershipService.Factory,
private val roomPushRuleServiceFactory: DefaultRoomPushRuleService.Factory, private val roomPushRuleServiceFactory: DefaultRoomPushRuleService.Factory,
private val roomAccountDataServiceFactory: RoomAccountDataService.Factory, private val roomAccountDataServiceFactory: DefaultRoomAccountDataService.Factory,
private val sendStateTask: SendStateTask, private val sendStateTask: SendStateTask,
private val viaParameterFinder: ViaParameterFinder, private val viaParameterFinder: ViaParameterFinder,
private val searchTask: SearchTask) : private val searchTask: SearchTask) :

View file

@ -20,34 +20,34 @@ import androidx.lifecycle.LiveData
import dagger.assisted.Assisted import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject import dagger.assisted.AssistedInject
import org.matrix.android.sdk.api.session.accountdata.AccountDataEvent
import org.matrix.android.sdk.api.session.accountdata.AccountDataService
import org.matrix.android.sdk.api.session.events.model.Content import org.matrix.android.sdk.api.session.events.model.Content
import org.matrix.android.sdk.api.session.room.accountdata.RoomAccountDataEvent
import org.matrix.android.sdk.api.session.room.accountdata.RoomAccountDataService
import org.matrix.android.sdk.api.util.Optional import org.matrix.android.sdk.api.util.Optional
internal class RoomAccountDataService @AssistedInject constructor(@Assisted private val roomId: String, internal class DefaultRoomAccountDataService @AssistedInject constructor(@Assisted private val roomId: String,
private val dataSource: RoomAccountDataDataSource, private val dataSource: RoomAccountDataDataSource,
private val updateRoomAccountDataTask: UpdateRoomAccountDataTask private val updateRoomAccountDataTask: UpdateRoomAccountDataTask
) : AccountDataService { ) : RoomAccountDataService {
@AssistedFactory @AssistedFactory
interface Factory { interface Factory {
fun create(roomId: String): RoomAccountDataService fun create(roomId: String): DefaultRoomAccountDataService
} }
override fun getAccountDataEvent(type: String): AccountDataEvent? { override fun getAccountDataEvent(type: String): RoomAccountDataEvent? {
return dataSource.getAccountDataEvent(roomId, type) return dataSource.getAccountDataEvent(roomId, type)
} }
override fun getLiveAccountDataEvent(type: String): LiveData<Optional<AccountDataEvent>> { override fun getLiveAccountDataEvent(type: String): LiveData<Optional<RoomAccountDataEvent>> {
return dataSource.getLiveAccountDataEvent(roomId, type) return dataSource.getLiveAccountDataEvent(roomId, type)
} }
override fun getAccountDataEvents(types: Set<String>): List<AccountDataEvent> { override fun getAccountDataEvents(types: Set<String>): List<RoomAccountDataEvent> {
return dataSource.getAccountDataEvents(roomId, types) return dataSource.getAccountDataEvents(roomId, types)
} }
override fun getLiveAccountDataEvents(types: Set<String>): LiveData<List<AccountDataEvent>> { override fun getLiveAccountDataEvents(types: Set<String>): LiveData<List<RoomAccountDataEvent>> {
return dataSource.getLiveAccountDataEvents(roomId, types) return dataSource.getLiveAccountDataEvents(roomId, types)
} }

View file

@ -20,14 +20,16 @@ import androidx.lifecycle.LiveData
import androidx.lifecycle.MediatorLiveData import androidx.lifecycle.MediatorLiveData
import androidx.lifecycle.Transformations import androidx.lifecycle.Transformations
import com.zhuinden.monarchy.Monarchy import com.zhuinden.monarchy.Monarchy
import org.matrix.android.sdk.api.session.accountdata.AccountDataEvent import io.realm.Realm
import io.realm.RealmQuery
import org.matrix.android.sdk.api.session.room.accountdata.RoomAccountDataEvent
import org.matrix.android.sdk.api.util.Optional import org.matrix.android.sdk.api.util.Optional
import org.matrix.android.sdk.api.util.toOptional import org.matrix.android.sdk.api.util.toOptional
import org.matrix.android.sdk.internal.database.RealmSessionProvider import org.matrix.android.sdk.internal.database.RealmSessionProvider
import org.matrix.android.sdk.internal.database.mapper.AccountDataMapper import org.matrix.android.sdk.internal.database.mapper.AccountDataMapper
import org.matrix.android.sdk.internal.database.model.RoomAccountDataEntityFields import org.matrix.android.sdk.internal.database.model.RoomAccountDataEntityFields
import org.matrix.android.sdk.internal.database.model.RoomEntity import org.matrix.android.sdk.internal.database.model.RoomEntity
import org.matrix.android.sdk.internal.database.query.where import org.matrix.android.sdk.internal.database.model.RoomEntityFields
import org.matrix.android.sdk.internal.di.SessionDatabase import org.matrix.android.sdk.internal.di.SessionDatabase
import javax.inject.Inject import javax.inject.Inject
@ -35,43 +37,62 @@ internal class RoomAccountDataDataSource @Inject constructor(@SessionDatabase pr
private val realmSessionProvider: RealmSessionProvider, private val realmSessionProvider: RealmSessionProvider,
private val accountDataMapper: AccountDataMapper) { private val accountDataMapper: AccountDataMapper) {
fun getAccountDataEvent(roomId: String, type: String): AccountDataEvent? { fun getAccountDataEvent(roomId: String, type: String): RoomAccountDataEvent? {
return getAccountDataEvents(roomId, setOf(type)).firstOrNull() return getAccountDataEvents(roomId, setOf(type)).firstOrNull()
} }
fun getLiveAccountDataEvent(roomId: String, type: String): LiveData<Optional<AccountDataEvent>> { fun getLiveAccountDataEvent(roomId: String, type: String): LiveData<Optional<RoomAccountDataEvent>> {
return Transformations.map(getLiveAccountDataEvents(roomId, setOf(type))) { return Transformations.map(getLiveAccountDataEvents(roomId, setOf(type))) {
it.firstOrNull()?.toOptional() it.firstOrNull()?.toOptional()
} }
} }
fun getAccountDataEvents(roomId: String, types: Set<String>): List<AccountDataEvent> { /**
* @param roomId the roomId to search for account data event. If null will check in every room.
* @param types the types to filter. If empty will return all account data event in given room (or every room if roomId is null)
*
*/
fun getAccountDataEvents(roomId: String?, types: Set<String>): List<RoomAccountDataEvent> {
return realmSessionProvider.withRealm { realm -> return realmSessionProvider.withRealm { realm ->
val roomEntity = RoomEntity.where(realm, roomId).findFirst() ?: return@withRealm emptyList() val roomEntity = buildRoomQuery(realm, roomId, types).findFirst() ?: return@withRealm emptyList()
roomEntity.accountDataEvents(types) roomEntity.accountDataEvents(types)
} }
} }
fun getLiveAccountDataEvents(roomId: String, types: Set<String>): LiveData<List<AccountDataEvent>> { /**
val liveRoomEntity = monarchy.findAllManagedWithChanges { RoomEntity.where(it, roomId) } * @param roomId the roomId to search for account data event. If null will check in every room.
val resultLiveData = MediatorLiveData<List<AccountDataEvent>>() * @param types the types to filter. If empty will return all account data event in the given room (or every room if roomId is null).
resultLiveData.addSource(liveRoomEntity) { *
val roomEntity = it.realmResults.firstOrNull() */
if (roomEntity == null) { fun getLiveAccountDataEvents(roomId: String?, types: Set<String>): LiveData<List<RoomAccountDataEvent>> {
resultLiveData.postValue(emptyList()) val liveRoomEntity = monarchy.findAllManagedWithChanges {
} else { buildRoomQuery(it, roomId, types)
val mappedResult = roomEntity.accountDataEvents(types) }
resultLiveData.postValue(mappedResult) val resultLiveData = MediatorLiveData<List<RoomAccountDataEvent>>()
} resultLiveData.addSource(liveRoomEntity) { changeSet ->
val mappedResult = changeSet.realmResults.flatMap { it.accountDataEvents(types) }
resultLiveData.postValue(mappedResult)
} }
return resultLiveData return resultLiveData
} }
private fun RoomEntity.accountDataEvents(types: Set<String>): List<AccountDataEvent> { private fun buildRoomQuery(realm: Realm, roomId: String?, types: Set<String>): RealmQuery<RoomEntity> {
val query = realm.where(RoomEntity::class.java)
if (roomId != null) {
query.equalTo(RoomEntityFields.ROOM_ID, roomId)
}
query.isNotEmpty(RoomEntityFields.ACCOUNT_DATA.`$`)
if (types.isNotEmpty()) {
query.`in`(RoomEntityFields.ACCOUNT_DATA.TYPE, types.toTypedArray())
}
return query
}
private fun RoomEntity.accountDataEvents(types: Set<String>): List<RoomAccountDataEvent> {
val query = accountData.where() val query = accountData.where()
if (types.isNotEmpty()) { if (types.isNotEmpty()) {
query.`in`(RoomAccountDataEntityFields.TYPE, types.toTypedArray()) query.`in`(RoomAccountDataEntityFields.TYPE, types.toTypedArray())
} }
return query.findAll().map { accountDataMapper.map(it) } return query.findAll().map { accountDataMapper.map(roomId, it) }
} }
} }

View file

@ -23,7 +23,7 @@ import io.realm.kotlin.where
import org.matrix.android.sdk.api.pushrules.RuleScope import org.matrix.android.sdk.api.pushrules.RuleScope
import org.matrix.android.sdk.api.pushrules.RuleSetKey import org.matrix.android.sdk.api.pushrules.RuleSetKey
import org.matrix.android.sdk.api.pushrules.rest.GetPushRulesResponse import org.matrix.android.sdk.api.pushrules.rest.GetPushRulesResponse
import org.matrix.android.sdk.api.session.accountdata.AccountDataEvent import org.matrix.android.sdk.api.session.accountdata.UserAccountDataEvent
import org.matrix.android.sdk.api.session.accountdata.UserAccountDataTypes import org.matrix.android.sdk.api.session.accountdata.UserAccountDataTypes
import org.matrix.android.sdk.api.session.events.model.Content import org.matrix.android.sdk.api.session.events.model.Content
import org.matrix.android.sdk.api.session.events.model.toModel import org.matrix.android.sdk.api.session.events.model.toModel
@ -113,7 +113,7 @@ internal class UserAccountDataSyncHandler @Inject constructor(
} }
} }
private fun handlePushRules(realm: Realm, event: AccountDataEvent) { private fun handlePushRules(realm: Realm, event: UserAccountDataEvent) {
val pushRules = event.content.toModel<GetPushRulesResponse>() ?: return val pushRules = event.content.toModel<GetPushRulesResponse>() ?: return
realm.where(PushRulesEntity::class.java) realm.where(PushRulesEntity::class.java)
.findAll() .findAll()
@ -155,7 +155,7 @@ internal class UserAccountDataSyncHandler @Inject constructor(
realm.insertOrUpdate(underrides) realm.insertOrUpdate(underrides)
} }
private fun handleDirectChatRooms(realm: Realm, event: AccountDataEvent) { private fun handleDirectChatRooms(realm: Realm, event: UserAccountDataEvent) {
val content = event.content.toModel<DirectMessagesContent>() ?: return val content = event.content.toModel<DirectMessagesContent>() ?: return
content.forEach { (userId, roomIds) -> content.forEach { (userId, roomIds) ->
roomIds.forEach { roomId -> roomIds.forEach { roomId ->
@ -181,7 +181,7 @@ internal class UserAccountDataSyncHandler @Inject constructor(
} }
} }
private fun handleIgnoredUsers(realm: Realm, event: AccountDataEvent) { private fun handleIgnoredUsers(realm: Realm, event: UserAccountDataEvent) {
val userIds = event.content.toModel<IgnoredUsersContent>()?.ignoredUsers?.keys ?: return val userIds = event.content.toModel<IgnoredUsersContent>()?.ignoredUsers?.keys ?: return
realm.where(IgnoredUserEntity::class.java) realm.where(IgnoredUserEntity::class.java)
.findAll() .findAll()
@ -191,7 +191,7 @@ internal class UserAccountDataSyncHandler @Inject constructor(
// TODO If not initial sync, we should execute a init sync // TODO If not initial sync, we should execute a init sync
} }
private fun handleBreadcrumbs(realm: Realm, event: AccountDataEvent) { private fun handleBreadcrumbs(realm: Realm, event: UserAccountDataEvent) {
val recentRoomIds = event.content.toModel<BreadcrumbsContent>()?.recentRoomIds ?: return val recentRoomIds = event.content.toModel<BreadcrumbsContent>()?.recentRoomIds ?: return
val entity = BreadcrumbsEntity.getOrCreate(realm) val entity = BreadcrumbsEntity.getOrCreate(realm)

View file

@ -18,9 +18,9 @@ package org.matrix.android.sdk.internal.session.sync.model.accountdata
import com.squareup.moshi.Json import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass import com.squareup.moshi.JsonClass
import org.matrix.android.sdk.api.session.accountdata.AccountDataEvent import org.matrix.android.sdk.api.session.accountdata.UserAccountDataEvent
@JsonClass(generateAdapter = true) @JsonClass(generateAdapter = true)
internal data class UserAccountDataSync( internal data class UserAccountDataSync(
@Json(name = "events") val list: List<AccountDataEvent> = emptyList() @Json(name = "events") val list: List<UserAccountDataEvent> = emptyList()
) )

View file

@ -56,7 +56,6 @@ internal class RoomSyncAccountDataHandler @Inject constructor(private val roomTa
private fun handleGeneric(roomEntity: RoomEntity, content: JsonDict?, eventType: String) { private fun handleGeneric(roomEntity: RoomEntity, content: JsonDict?, eventType: String) {
val existing = roomEntity.accountData.where().equalTo(RoomAccountDataEntityFields.TYPE, eventType).findFirst() val existing = roomEntity.accountData.where().equalTo(RoomAccountDataEntityFields.TYPE, eventType).findFirst()
if (existing != null) { if (existing != null) {
// Update current value
existing.contentStr = ContentMapper.map(content) existing.contentStr = ContentMapper.map(content)
} else { } else {
val roomAccountData = RoomAccountDataEntity( val roomAccountData = RoomAccountDataEntity(

View file

@ -18,42 +18,53 @@ package org.matrix.android.sdk.internal.session.user.accountdata
import androidx.lifecycle.LiveData import androidx.lifecycle.LiveData
import com.zhuinden.monarchy.Monarchy import com.zhuinden.monarchy.Monarchy
import org.matrix.android.sdk.api.session.accountdata.AccountDataService import org.matrix.android.sdk.api.session.accountdata.SessionAccountDataService
import org.matrix.android.sdk.api.session.events.model.Content import org.matrix.android.sdk.api.session.events.model.Content
import org.matrix.android.sdk.api.util.Optional import org.matrix.android.sdk.api.util.Optional
import org.matrix.android.sdk.internal.di.SessionDatabase import org.matrix.android.sdk.internal.di.SessionDatabase
import org.matrix.android.sdk.internal.session.sync.UserAccountDataSyncHandler import org.matrix.android.sdk.internal.session.sync.UserAccountDataSyncHandler
import org.matrix.android.sdk.api.session.accountdata.AccountDataEvent import org.matrix.android.sdk.api.session.accountdata.UserAccountDataEvent
import org.matrix.android.sdk.api.session.room.accountdata.RoomAccountDataEvent
import org.matrix.android.sdk.internal.session.room.accountdata.RoomAccountDataDataSource
import org.matrix.android.sdk.internal.task.TaskExecutor import org.matrix.android.sdk.internal.task.TaskExecutor
import org.matrix.android.sdk.internal.task.configureWith import org.matrix.android.sdk.internal.task.configureWith
import org.matrix.android.sdk.internal.util.awaitCallback import org.matrix.android.sdk.internal.util.awaitCallback
import javax.inject.Inject import javax.inject.Inject
internal class UserAccountDataService @Inject constructor( internal class DefaultSessionAccountDataService @Inject constructor(
@SessionDatabase private val monarchy: Monarchy, @SessionDatabase private val monarchy: Monarchy,
private val updateUserAccountDataTask: UpdateUserAccountDataTask, private val updateUserAccountDataTask: UpdateUserAccountDataTask,
private val userAccountDataSyncHandler: UserAccountDataSyncHandler, private val userAccountDataSyncHandler: UserAccountDataSyncHandler,
private val accountDataDataSource: UserAccountDataDataSource, private val userAccountDataDataSource: UserAccountDataDataSource,
private val roomAccountDataDataSource: RoomAccountDataDataSource,
private val taskExecutor: TaskExecutor private val taskExecutor: TaskExecutor
) : AccountDataService { ) : SessionAccountDataService {
override fun getAccountDataEvent(type: String): AccountDataEvent? { override fun getUserAccountDataEvent(type: String): UserAccountDataEvent? {
return accountDataDataSource.getAccountDataEvent(type) return userAccountDataDataSource.getAccountDataEvent(type)
} }
override fun getLiveAccountDataEvent(type: String): LiveData<Optional<AccountDataEvent>> { override fun getLiveUserAccountDataEvent(type: String): LiveData<Optional<UserAccountDataEvent>> {
return accountDataDataSource.getLiveAccountDataEvent(type) return userAccountDataDataSource.getLiveAccountDataEvent(type)
} }
override fun getAccountDataEvents(types: Set<String>): List<AccountDataEvent> { override fun getUserAccountDataEvents(types: Set<String>): List<UserAccountDataEvent> {
return accountDataDataSource.getAccountDataEvents(types) return userAccountDataDataSource.getAccountDataEvents(types)
} }
override fun getLiveAccountDataEvents(types: Set<String>): LiveData<List<AccountDataEvent>> { override fun getLiveUserAccountDataEvents(types: Set<String>): LiveData<List<UserAccountDataEvent>> {
return accountDataDataSource.getLiveAccountDataEvents(types) return userAccountDataDataSource.getLiveAccountDataEvents(types)
} }
override suspend fun updateAccountData(type: String, content: Content) { override fun getRoomAccountDataEvents(types: Set<String>): List<RoomAccountDataEvent> {
return roomAccountDataDataSource.getAccountDataEvents(null, types)
}
override fun getLiveRoomAccountDataEvents(types: Set<String>): LiveData<List<RoomAccountDataEvent>> {
return roomAccountDataDataSource.getLiveAccountDataEvents(null, types)
}
override suspend fun updateUserAccountData(type: String, content: Content) {
val params = UpdateUserAccountDataTask.AnyParams(type = type, any = content) val params = UpdateUserAccountDataTask.AnyParams(type = type, any = content)
awaitCallback<Unit> { callback -> awaitCallback<Unit> { callback ->
updateUserAccountDataTask.configureWith(params) { updateUserAccountDataTask.configureWith(params) {

View file

@ -21,7 +21,7 @@ import androidx.lifecycle.Transformations
import com.zhuinden.monarchy.Monarchy import com.zhuinden.monarchy.Monarchy
import io.realm.Realm import io.realm.Realm
import io.realm.RealmQuery import io.realm.RealmQuery
import org.matrix.android.sdk.api.session.accountdata.AccountDataEvent import org.matrix.android.sdk.api.session.accountdata.UserAccountDataEvent
import org.matrix.android.sdk.api.util.Optional import org.matrix.android.sdk.api.util.Optional
import org.matrix.android.sdk.api.util.toOptional import org.matrix.android.sdk.api.util.toOptional
import org.matrix.android.sdk.internal.database.RealmSessionProvider import org.matrix.android.sdk.internal.database.RealmSessionProvider
@ -35,23 +35,23 @@ internal class UserAccountDataDataSource @Inject constructor(@SessionDatabase pr
private val realmSessionProvider: RealmSessionProvider, private val realmSessionProvider: RealmSessionProvider,
private val accountDataMapper: AccountDataMapper) { private val accountDataMapper: AccountDataMapper) {
fun getAccountDataEvent(type: String): AccountDataEvent? { fun getAccountDataEvent(type: String): UserAccountDataEvent? {
return getAccountDataEvents(setOf(type)).firstOrNull() return getAccountDataEvents(setOf(type)).firstOrNull()
} }
fun getLiveAccountDataEvent(type: String): LiveData<Optional<AccountDataEvent>> { fun getLiveAccountDataEvent(type: String): LiveData<Optional<UserAccountDataEvent>> {
return Transformations.map(getLiveAccountDataEvents(setOf(type))) { return Transformations.map(getLiveAccountDataEvents(setOf(type))) {
it.firstOrNull()?.toOptional() it.firstOrNull()?.toOptional()
} }
} }
fun getAccountDataEvents(types: Set<String>): List<AccountDataEvent> { fun getAccountDataEvents(types: Set<String>): List<UserAccountDataEvent> {
return realmSessionProvider.withRealm { return realmSessionProvider.withRealm {
accountDataEventsQuery(it, types).findAll().map(accountDataMapper::map) accountDataEventsQuery(it, types).findAll().map(accountDataMapper::map)
} }
} }
fun getLiveAccountDataEvents(types: Set<String>): LiveData<List<AccountDataEvent>> { fun getLiveAccountDataEvents(types: Set<String>): LiveData<List<UserAccountDataEvent>> {
return monarchy.findAllMappedWithChanges( return monarchy.findAllMappedWithChanges(
{ accountDataEventsQuery(it, types) }, { accountDataEventsQuery(it, types) },
accountDataMapper::map accountDataMapper::map

View file

@ -23,7 +23,7 @@ import androidx.lifecycle.LiveData
import androidx.lifecycle.Transformations import androidx.lifecycle.Transformations
import org.matrix.android.sdk.api.query.QueryStringValue import org.matrix.android.sdk.api.query.QueryStringValue
import org.matrix.android.sdk.api.session.Session import org.matrix.android.sdk.api.session.Session
import org.matrix.android.sdk.api.session.accountdata.AccountDataEvent import org.matrix.android.sdk.api.session.accountdata.UserAccountDataEvent
import org.matrix.android.sdk.api.session.accountdata.UserAccountDataTypes import org.matrix.android.sdk.api.session.accountdata.UserAccountDataTypes
import org.matrix.android.sdk.api.session.events.model.Content import org.matrix.android.sdk.api.session.events.model.Content
import org.matrix.android.sdk.api.session.events.model.Event import org.matrix.android.sdk.api.session.events.model.Event
@ -47,7 +47,7 @@ import javax.inject.Inject
@SessionScope @SessionScope
internal class WidgetManager @Inject constructor(private val integrationManager: IntegrationManager, internal class WidgetManager @Inject constructor(private val integrationManager: IntegrationManager,
private val accountDataDataSource: UserAccountDataDataSource, private val userAccountDataDataSource: UserAccountDataDataSource,
private val stateEventDataSource: StateEventDataSource, private val stateEventDataSource: StateEventDataSource,
private val createWidgetTask: CreateWidgetTask, private val createWidgetTask: CreateWidgetTask,
private val widgetFactory: WidgetFactory, private val widgetFactory: WidgetFactory,
@ -136,7 +136,7 @@ internal class WidgetManager @Inject constructor(private val integrationManager:
widgetTypes: Set<String>? = null, widgetTypes: Set<String>? = null,
excludedTypes: Set<String>? = null excludedTypes: Set<String>? = null
): LiveData<List<Widget>> { ): LiveData<List<Widget>> {
val widgetsAccountData = accountDataDataSource.getLiveAccountDataEvent(UserAccountDataTypes.TYPE_WIDGETS) val widgetsAccountData = userAccountDataDataSource.getLiveAccountDataEvent(UserAccountDataTypes.TYPE_WIDGETS)
return Transformations.map(widgetsAccountData) { return Transformations.map(widgetsAccountData) {
it.getOrNull()?.mapToWidgets(widgetTypes, excludedTypes).orEmpty() it.getOrNull()?.mapToWidgets(widgetTypes, excludedTypes).orEmpty()
} }
@ -146,12 +146,12 @@ internal class WidgetManager @Inject constructor(private val integrationManager:
widgetTypes: Set<String>? = null, widgetTypes: Set<String>? = null,
excludedTypes: Set<String>? = null excludedTypes: Set<String>? = null
): List<Widget> { ): List<Widget> {
val widgetsAccountData = accountDataDataSource.getAccountDataEvent(UserAccountDataTypes.TYPE_WIDGETS) ?: return emptyList() val widgetsAccountData = userAccountDataDataSource.getAccountDataEvent(UserAccountDataTypes.TYPE_WIDGETS) ?: return emptyList()
return widgetsAccountData.mapToWidgets(widgetTypes, excludedTypes) return widgetsAccountData.mapToWidgets(widgetTypes, excludedTypes)
} }
private fun AccountDataEvent.mapToWidgets(widgetTypes: Set<String>? = null, private fun UserAccountDataEvent.mapToWidgets(widgetTypes: Set<String>? = null,
excludedTypes: Set<String>? = null): List<Widget> { excludedTypes: Set<String>? = null): List<Widget> {
return extractWidgetSequence(widgetFactory) return extractWidgetSequence(widgetFactory)
.filter { .filter {
val widgetType = it.widgetContent.type ?: return@filter false val widgetType = it.widgetContent.type ?: return@filter false

View file

@ -19,10 +19,10 @@ package org.matrix.android.sdk.internal.session.widgets.helper
import org.matrix.android.sdk.api.session.events.model.Event import org.matrix.android.sdk.api.session.events.model.Event
import org.matrix.android.sdk.api.session.events.model.toModel import org.matrix.android.sdk.api.session.events.model.toModel
import org.matrix.android.sdk.api.util.JsonDict import org.matrix.android.sdk.api.util.JsonDict
import org.matrix.android.sdk.api.session.accountdata.AccountDataEvent import org.matrix.android.sdk.api.session.accountdata.UserAccountDataEvent
import org.matrix.android.sdk.api.session.widgets.model.Widget import org.matrix.android.sdk.api.session.widgets.model.Widget
internal fun AccountDataEvent.extractWidgetSequence(widgetFactory: WidgetFactory): Sequence<Widget> { internal fun UserAccountDataEvent.extractWidgetSequence(widgetFactory: WidgetFactory): Sequence<Widget> {
return content.asSequence() return content.asSequence()
.mapNotNull { .mapNotNull {
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")

View file

@ -0,0 +1 @@
Splits SessionAccountDataService and RoomAccountDataService and offers to query RoomAccountDataEvent at the session level.

View file

@ -252,7 +252,7 @@ class KeysBackupRestoreSharedViewModel @Inject constructor(
} }
private fun isBackupKeyInQuadS(): Boolean { private fun isBackupKeyInQuadS(): Boolean {
val sssBackupSecret = session.userAccountDataService().getAccountDataEvent(KEYBACKUP_SECRET_SSSS_NAME) val sssBackupSecret = session.accountDataService().getUserAccountDataEvent(KEYBACKUP_SECRET_SSSS_NAME)
?: return false ?: return false
// Some sanity ? // Some sanity ?

View file

@ -218,7 +218,7 @@ class SharedSecureStorageViewModel @AssistedInject constructor(
withContext(Dispatchers.IO) { withContext(Dispatchers.IO) {
args.requestedSecrets.forEach { args.requestedSecrets.forEach {
if (session.userAccountDataService().getAccountDataEvent(it) != null) { if (session.accountDataService().getUserAccountDataEvent(it) != null) {
val res = session.sharedSecretStorageService.getSecret( val res = session.sharedSecretStorageService.getSecret(
name = it, name = it,
keyId = keyInfo.id, keyId = keyInfo.id,
@ -287,7 +287,7 @@ class SharedSecureStorageViewModel @AssistedInject constructor(
withContext(Dispatchers.IO) { withContext(Dispatchers.IO) {
args.requestedSecrets.forEach { args.requestedSecrets.forEach {
if (session.userAccountDataService().getAccountDataEvent(it) != null) { if (session.accountDataService().getUserAccountDataEvent(it) != null) {
val res = session.sharedSecretStorageService.getSecret( val res = session.sharedSecretStorageService.getSecret(
name = it, name = it,
keyId = keyInfo.id, keyId = keyInfo.id,

View file

@ -26,7 +26,7 @@ import im.vector.app.core.epoxy.loadingItem
import im.vector.app.core.resources.StringProvider import im.vector.app.core.resources.StringProvider
import im.vector.app.core.ui.list.genericFooterItem import im.vector.app.core.ui.list.genericFooterItem
import im.vector.app.core.ui.list.genericWithValueItem import im.vector.app.core.ui.list.genericWithValueItem
import org.matrix.android.sdk.api.session.accountdata.AccountDataEvent import org.matrix.android.sdk.api.session.accountdata.UserAccountDataEvent
import javax.inject.Inject import javax.inject.Inject
class AccountDataEpoxyController @Inject constructor( class AccountDataEpoxyController @Inject constructor(
@ -34,8 +34,8 @@ class AccountDataEpoxyController @Inject constructor(
) : TypedEpoxyController<AccountDataViewState>() { ) : TypedEpoxyController<AccountDataViewState>() {
interface InteractionListener { interface InteractionListener {
fun didTap(data: AccountDataEvent) fun didTap(data: UserAccountDataEvent)
fun didLongTap(data: AccountDataEvent) fun didLongTap(data: UserAccountDataEvent)
} }
var interactionListener: InteractionListener? = null var interactionListener: InteractionListener? = null

View file

@ -35,7 +35,7 @@ import im.vector.app.core.utils.createJSonViewerStyleProvider
import im.vector.app.databinding.FragmentGenericRecyclerBinding import im.vector.app.databinding.FragmentGenericRecyclerBinding
import org.billcarsonfr.jsonviewer.JSonViewerDialog import org.billcarsonfr.jsonviewer.JSonViewerDialog
import org.matrix.android.sdk.api.session.accountdata.AccountDataEvent import org.matrix.android.sdk.api.session.accountdata.UserAccountDataEvent
import org.matrix.android.sdk.internal.di.MoshiProvider import org.matrix.android.sdk.internal.di.MoshiProvider
import javax.inject.Inject import javax.inject.Inject
@ -73,9 +73,9 @@ class AccountDataFragment @Inject constructor(
super.onDestroyView() super.onDestroyView()
} }
override fun didTap(data: AccountDataEvent) { override fun didTap(data: UserAccountDataEvent) {
val jsonString = MoshiProvider.providesMoshi() val jsonString = MoshiProvider.providesMoshi()
.adapter(AccountDataEvent::class.java) .adapter(UserAccountDataEvent::class.java)
.toJson(data) .toJson(data)
JSonViewerDialog.newInstance( JSonViewerDialog.newInstance(
jsonString, jsonString,
@ -84,7 +84,7 @@ class AccountDataFragment @Inject constructor(
).show(childFragmentManager, "JSON_VIEWER") ).show(childFragmentManager, "JSON_VIEWER")
} }
override fun didLongTap(data: AccountDataEvent) { override fun didLongTap(data: UserAccountDataEvent) {
MaterialAlertDialogBuilder(requireActivity()) MaterialAlertDialogBuilder(requireActivity())
.setTitle(R.string.delete) .setTitle(R.string.delete)
.setMessage(getString(R.string.delete_account_data_warning, data.type)) .setMessage(getString(R.string.delete_account_data_warning, data.type))

View file

@ -31,11 +31,11 @@ import im.vector.app.core.platform.EmptyViewEvents
import im.vector.app.core.platform.VectorViewModel import im.vector.app.core.platform.VectorViewModel
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import org.matrix.android.sdk.api.session.Session import org.matrix.android.sdk.api.session.Session
import org.matrix.android.sdk.api.session.accountdata.AccountDataEvent import org.matrix.android.sdk.api.session.accountdata.UserAccountDataEvent
import org.matrix.android.sdk.rx.rx import org.matrix.android.sdk.rx.rx
data class AccountDataViewState( data class AccountDataViewState(
val accountData: Async<List<AccountDataEvent>> = Uninitialized val accountData: Async<List<UserAccountDataEvent>> = Uninitialized
) : MvRxState ) : MvRxState
class AccountDataViewModel @AssistedInject constructor(@Assisted initialState: AccountDataViewState, class AccountDataViewModel @AssistedInject constructor(@Assisted initialState: AccountDataViewState,
@ -57,7 +57,7 @@ class AccountDataViewModel @AssistedInject constructor(@Assisted initialState: A
private fun handleDeleteAccountData(action: AccountDataAction.DeleteAccountData) { private fun handleDeleteAccountData(action: AccountDataAction.DeleteAccountData) {
viewModelScope.launch { viewModelScope.launch {
session.userAccountDataService().updateAccountData(action.type, emptyMap()) session.accountDataService().updateUserAccountData(action.type, emptyMap())
} }
} }

View file

@ -284,7 +284,7 @@ class WidgetPostAPIHandler @AssistedInject constructor(@Assisted private val roo
) )
) )
launchWidgetAPIAction(widgetPostAPIMediator, eventData) { launchWidgetAPIAction(widgetPostAPIMediator, eventData) {
session.userAccountDataService().updateAccountData( session.accountDataService().updateUserAccountData(
type = UserAccountDataTypes.TYPE_WIDGETS, type = UserAccountDataTypes.TYPE_WIDGETS,
content = addUserWidgetBody content = addUserWidgetBody
) )

View file

@ -35,7 +35,7 @@ import io.reactivex.functions.Function4
import io.reactivex.subjects.PublishSubject import io.reactivex.subjects.PublishSubject
import org.matrix.android.sdk.api.extensions.orFalse import org.matrix.android.sdk.api.extensions.orFalse
import org.matrix.android.sdk.api.session.Session import org.matrix.android.sdk.api.session.Session
import org.matrix.android.sdk.api.session.accountdata.AccountDataEvent import org.matrix.android.sdk.api.session.accountdata.UserAccountDataEvent
import org.matrix.android.sdk.api.session.crypto.crosssigning.MASTER_KEY_SSSS_NAME import org.matrix.android.sdk.api.session.crypto.crosssigning.MASTER_KEY_SSSS_NAME
import org.matrix.android.sdk.api.session.crypto.crosssigning.MXCrossSigningInfo import org.matrix.android.sdk.api.session.crypto.crosssigning.MXCrossSigningInfo
import org.matrix.android.sdk.api.session.crypto.crosssigning.SELF_SIGNING_KEY_SSSS_NAME import org.matrix.android.sdk.api.session.crypto.crosssigning.SELF_SIGNING_KEY_SSSS_NAME
@ -98,7 +98,7 @@ class ServerBackupStatusViewModel @AssistedInject constructor(@Assisted initialS
keysBackupState.value = session.cryptoService().keysBackupService().state keysBackupState.value = session.cryptoService().keysBackupService().state
Observable.combineLatest<List<AccountDataEvent>, Optional<MXCrossSigningInfo>, KeysBackupState, Optional<PrivateKeysInfo>, BannerState>( Observable.combineLatest<List<UserAccountDataEvent>, Optional<MXCrossSigningInfo>, KeysBackupState, Optional<PrivateKeysInfo>, BannerState>(
session.rx().liveUserAccountData(setOf(MASTER_KEY_SSSS_NAME, USER_SIGNING_KEY_SSSS_NAME, SELF_SIGNING_KEY_SSSS_NAME)), session.rx().liveUserAccountData(setOf(MASTER_KEY_SSSS_NAME, USER_SIGNING_KEY_SSSS_NAME, SELF_SIGNING_KEY_SSSS_NAME)),
session.rx().liveCrossSigningInfo(session.myUserId), session.rx().liveCrossSigningInfo(session.myUserId),
keyBackupPublishSubject, keyBackupPublishSubject,