Code review

This commit is contained in:
Valere 2020-02-14 10:15:32 +01:00 committed by Valere
parent e0eede1150
commit f99eca8014
13 changed files with 91 additions and 96 deletions

View File

@ -124,9 +124,9 @@ class RxSession(private val session: Session) {
}
fun liveAccountData(filter: List<String>): Observable<List<UserAccountDataEvent>> {
return session.getLiveAccountData(filter).asObservable()
return session.getLiveAccountDataEvents(filter).asObservable()
.startWithCallable {
session.getAccountData(filter)
session.getAccountDataEvents(filter)
}
}
}

View File

@ -25,7 +25,7 @@ import im.vector.matrix.android.api.session.Session
import im.vector.matrix.android.api.session.securestorage.Curve25519AesSha2KeySpec
import im.vector.matrix.android.api.session.securestorage.EncryptedSecretContent
import im.vector.matrix.android.api.session.securestorage.KeySigner
import im.vector.matrix.android.api.session.securestorage.SSSSKeyCreationInfo
import im.vector.matrix.android.api.session.securestorage.SsssKeyCreationInfo
import im.vector.matrix.android.api.session.securestorage.SecretStorageKeyContent
import im.vector.matrix.android.api.util.Optional
import im.vector.matrix.android.common.CommonTestHelper
@ -33,8 +33,9 @@ import im.vector.matrix.android.common.CryptoTestHelper
import im.vector.matrix.android.common.SessionTestParams
import im.vector.matrix.android.common.TestConstants
import im.vector.matrix.android.common.TestMatrixCallback
import im.vector.matrix.android.internal.crypto.SSSS_ALGORITHM_CURVE25519_AES_SHA2
import im.vector.matrix.android.internal.crypto.crosssigning.toBase64NoPadding
import im.vector.matrix.android.internal.crypto.secrets.DefaultSharedSecretStorage
import im.vector.matrix.android.internal.crypto.secrets.DefaultSharedSecretStorageService
import im.vector.matrix.android.internal.session.sync.model.accountdata.UserAccountDataEvent
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
@ -74,8 +75,8 @@ class QuadSTests : InstrumentedTest {
val TEST_KEY_ID = "my.test.Key"
quadS.generateKey(TEST_KEY_ID, "Test Key", emptyKeySigner,
object : MatrixCallback<SSSSKeyCreationInfo> {
override fun onSuccess(data: SSSSKeyCreationInfo) {
object : MatrixCallback<SsssKeyCreationInfo> {
override fun onSuccess(data: SsssKeyCreationInfo) {
recoveryKey = data.recoveryKey
aliceLatch.countDown()
}
@ -93,7 +94,7 @@ class QuadSTests : InstrumentedTest {
var accountData: UserAccountDataEvent? = null
val liveAccountData = runBlocking(Dispatchers.Main) {
aliceSession.getLiveAccountData("m.secret_storage.key.$TEST_KEY_ID")
aliceSession.getLiveAccountDataEvent("m.secret_storage.key.$TEST_KEY_ID")
}
val accountDataObserver = Observer<Optional<UserAccountDataEvent>?> { t ->
if (t?.getOrNull()?.type == "m.secret_storage.key.$TEST_KEY_ID") {
@ -108,13 +109,13 @@ class QuadSTests : InstrumentedTest {
Assert.assertNotNull("Key should be stored in account data", accountData)
val parsed = SecretStorageKeyContent.fromJson(accountData!!.content)
Assert.assertNotNull("Key Content cannot be parsed", parsed)
Assert.assertEquals("Unexpected Algorithm", DefaultSharedSecretStorage.ALGORITHM_CURVE25519_AES_SHA2, parsed!!.algorithm)
Assert.assertEquals("Unexpected Algorithm", SSSS_ALGORITHM_CURVE25519_AES_SHA2, parsed!!.algorithm)
Assert.assertEquals("Unexpected key name", "Test Key", parsed.name)
Assert.assertNull("Key was not generated from passphrase", parsed.passphrase)
Assert.assertNotNull("Pubkey should be defined", parsed.publicKey)
val privateKeySpec = Curve25519AesSha2KeySpec.fromRecoveryKey(recoveryKey!!)
DefaultSharedSecretStorage.withOlmDecryption { olmPkDecryption ->
DefaultSharedSecretStorageService.withOlmDecryption { olmPkDecryption ->
val pubKey = olmPkDecryption.setPrivateKey(privateKeySpec!!.privateKey)
Assert.assertEquals("Unexpected Public Key", pubKey, parsed.publicKey)
}
@ -126,10 +127,10 @@ class QuadSTests : InstrumentedTest {
val defaultDataLock = CountDownLatch(1)
val liveDefAccountData = runBlocking(Dispatchers.Main) {
aliceSession.getLiveAccountData(DefaultSharedSecretStorage.DEFAULT_KEY_ID)
aliceSession.getLiveAccountDataEvent(DefaultSharedSecretStorageService.DEFAULT_KEY_ID)
}
val accountDefDataObserver = Observer<Optional<UserAccountDataEvent>?> { t ->
if (t?.getOrNull()?.type == DefaultSharedSecretStorage.DEFAULT_KEY_ID) {
if (t?.getOrNull()?.type == DefaultSharedSecretStorageService.DEFAULT_KEY_ID) {
defaultKeyAccountData = t.getOrNull()!!
defaultDataLock.countDown()
}
@ -247,7 +248,7 @@ class QuadSTests : InstrumentedTest {
)
mTestHelper.await(storeLatch)
val accountDataEvent = aliceSession.getAccountData("my.secret")
val accountDataEvent = aliceSession.getAccountDataEvent("my.secret")
val encryptedContent = accountDataEvent?.content?.get("encrypted") as? Map<*, *>
Assert.assertEquals("Content should contains two encryptions", 2, encryptedContent?.keys?.size ?: 0)
@ -334,7 +335,7 @@ class QuadSTests : InstrumentedTest {
var accountData: UserAccountDataEvent? = null
val liveAccountData = runBlocking(Dispatchers.Main) {
session.getLiveAccountData(type)
session.getLiveAccountDataEvent(type)
}
val accountDataObserver = Observer<Optional<UserAccountDataEvent>?> { t ->
if (t?.getOrNull()?.type == type) {
@ -350,7 +351,7 @@ class QuadSTests : InstrumentedTest {
return accountData!!
}
private fun generatedSecret(session: Session, keyId: String, asDefault: Boolean = true): SSSSKeyCreationInfo {
private fun generatedSecret(session: Session, keyId: String, asDefault: Boolean = true): SsssKeyCreationInfo {
val quadS = session.sharedSecretStorageService
val emptyKeySigner = object : KeySigner {
@ -359,13 +360,13 @@ class QuadSTests : InstrumentedTest {
}
}
var creationInfo: SSSSKeyCreationInfo? = null
var creationInfo: SsssKeyCreationInfo? = null
val generateLatch = CountDownLatch(1)
quadS.generateKey(keyId, keyId, emptyKeySigner,
object : MatrixCallback<SSSSKeyCreationInfo> {
override fun onSuccess(data: SSSSKeyCreationInfo) {
object : MatrixCallback<SsssKeyCreationInfo> {
override fun onSuccess(data: SsssKeyCreationInfo) {
creationInfo = data
generateLatch.countDown()
}
@ -385,13 +386,13 @@ class QuadSTests : InstrumentedTest {
val setDefaultLatch = CountDownLatch(1)
quadS.setDefaultKey(keyId, TestMatrixCallback(setDefaultLatch))
mTestHelper.await(setDefaultLatch)
assertAccountData(session, DefaultSharedSecretStorage.DEFAULT_KEY_ID)
assertAccountData(session, DefaultSharedSecretStorageService.DEFAULT_KEY_ID)
}
return creationInfo!!
}
private fun generatedSecretFromPassphrase(session: Session, passphrase: String, keyId: String, asDefault: Boolean = true): SSSSKeyCreationInfo {
private fun generatedSecretFromPassphrase(session: Session, passphrase: String, keyId: String, asDefault: Boolean = true): SsssKeyCreationInfo {
val quadS = session.sharedSecretStorageService
val emptyKeySigner = object : KeySigner {
@ -400,7 +401,7 @@ class QuadSTests : InstrumentedTest {
}
}
var creationInfo: SSSSKeyCreationInfo? = null
var creationInfo: SsssKeyCreationInfo? = null
val generateLatch = CountDownLatch(1)
@ -408,8 +409,8 @@ class QuadSTests : InstrumentedTest {
passphrase,
emptyKeySigner,
null,
object : MatrixCallback<SSSSKeyCreationInfo> {
override fun onSuccess(data: SSSSKeyCreationInfo) {
object : MatrixCallback<SsssKeyCreationInfo> {
override fun onSuccess(data: SsssKeyCreationInfo) {
creationInfo = data
generateLatch.countDown()
}
@ -429,7 +430,7 @@ class QuadSTests : InstrumentedTest {
val setDefaultLatch = CountDownLatch(1)
quadS.setDefaultKey(keyId, TestMatrixCallback(setDefaultLatch))
mTestHelper.await(setDefaultLatch)
assertAccountData(session, DefaultSharedSecretStorage.DEFAULT_KEY_ID)
assertAccountData(session, DefaultSharedSecretStorageService.DEFAULT_KEY_ID)
}
return creationInfo!!

View File

@ -24,13 +24,13 @@ import im.vector.matrix.android.internal.session.sync.model.accountdata.UserAcco
interface AccountDataService {
fun getAccountData(type: String): UserAccountDataEvent?
fun getAccountDataEvent(type: String): UserAccountDataEvent?
fun getLiveAccountData(type: String): LiveData<Optional<UserAccountDataEvent>>
fun getLiveAccountDataEvent(type: String): LiveData<Optional<UserAccountDataEvent>>
fun getAccountData(filterType: List<String>): List<UserAccountDataEvent>
fun getAccountDataEvents(filterType: List<String>): List<UserAccountDataEvent>
fun getLiveAccountData(filterType: List<String>): LiveData<List<UserAccountDataEvent>>
fun getLiveAccountDataEvents(filterType: List<String>): LiveData<List<UserAccountDataEvent>>
fun updateAccountData(type: String, content: Content, callback: MatrixCallback<Unit>? = null)
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2019 New Vector Ltd
* Copyright 2020 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -31,26 +31,38 @@ import im.vector.matrix.android.api.listeners.ProgressListener
interface SharedSecretStorageService {
/**
* Add a key for encrypting secrets.
* Generates a SSSS key for encrypting secrets.
* Use the SsssKeyCreationInfo object returned by the callback to get more information about the created key (recovery key ...)
*
* @param algorithm the algorithm used by the key.
* @param opts the options for the algorithm. The properties used
* depend on the algorithm given.
* @param keyId the ID of the key
* @param keyName a human readable name
* @param keySigner Used to add a signature to the key (client should check key signature before storing secret)
*
* @return {string} the ID of the key
* @param callback Get key creation info
*/
fun generateKey(keyId: String,
keyName: String,
keySigner: KeySigner,
callback: MatrixCallback<SSSSKeyCreationInfo>)
callback: MatrixCallback<SsssKeyCreationInfo>)
/**
* Generates a SSSS key using the given passphrase.
* Use the SsssKeyCreationInfo object returned by the callback to get more information about the created key (recovery key, salt, iteration ...)
*
* @param keyId the ID of the key
* @param keyName human readable key name
* @param passphrase The passphrase used to generate the key
* @param keySigner Used to add a signature to the key (client should check key signature before retrieving secret)
* @param progressListener The derivation of the passphrase may take long depending on the device, use this to report progress
*
* @param callback Get key creation info
*/
fun generateKeyWithPassphrase(keyId: String,
keyName: String,
passphrase: String,
keySigner: KeySigner,
progressListener: ProgressListener?,
callback: MatrixCallback<SSSSKeyCreationInfo>)
callback: MatrixCallback<SsssKeyCreationInfo>)
fun getKey(keyId: String): KeyInfoResult
@ -92,11 +104,9 @@ interface SharedSecretStorageService {
*
* @param name The name of the secret
* @param keyId The id of the key that should be used to decrypt (null for default key)
* @param privateKey the passphrase/secret
* @param secretKey the secret key to use (@see #Curve25519AesSha2KeySpec)
*
* @return The decrypted value
*/
@Throws
fun getSecret(name: String, keyId: String?, secretKey: SSSSKeySpec, callback: MatrixCallback<String>)
}

View File

@ -16,7 +16,7 @@
package im.vector.matrix.android.api.session.securestorage
data class SSSSKeyCreationInfo(
data class SsssKeyCreationInfo(
val keyId: String = "",
var content: SecretStorageKeyContent?,
val recoveryKey: String = ""

View File

@ -31,6 +31,11 @@ const val MXCRYPTO_ALGORITHM_MEGOLM = "m.megolm.v1.aes-sha2"
*/
const val MXCRYPTO_ALGORITHM_MEGOLM_BACKUP = "m.megolm_backup.v1.curve25519-aes-sha2"
/**
* Secured Shared Storage algorithm constant
*/
const val SSSS_ALGORITHM_CURVE25519_AES_SHA2 = "m.secret_storage.v1.curve25519-aes-sha2"
// TODO Refacto: use this constants everywhere
const val ed25519 = "ed25519"
const val curve25519 = "curve25519"

View File

@ -25,12 +25,13 @@ import im.vector.matrix.android.api.session.securestorage.EncryptedSecretContent
import im.vector.matrix.android.api.session.securestorage.KeyInfo
import im.vector.matrix.android.api.session.securestorage.KeyInfoResult
import im.vector.matrix.android.api.session.securestorage.KeySigner
import im.vector.matrix.android.api.session.securestorage.SSSSKeyCreationInfo
import im.vector.matrix.android.api.session.securestorage.SsssKeyCreationInfo
import im.vector.matrix.android.api.session.securestorage.SSSSKeySpec
import im.vector.matrix.android.api.session.securestorage.SSSSPassphrase
import im.vector.matrix.android.api.session.securestorage.SecretStorageKeyContent
import im.vector.matrix.android.api.session.securestorage.SharedSecretStorageError
import im.vector.matrix.android.api.session.securestorage.SharedSecretStorageService
import im.vector.matrix.android.internal.crypto.SSSS_ALGORITHM_CURVE25519_AES_SHA2
import im.vector.matrix.android.internal.crypto.keysbackup.generatePrivateKeyWithPassword
import im.vector.matrix.android.internal.crypto.keysbackup.util.computeRecoveryKey
import im.vector.matrix.android.internal.extensions.foldToCallback
@ -42,7 +43,7 @@ import org.matrix.olm.OlmPkEncryption
import org.matrix.olm.OlmPkMessage
import javax.inject.Inject
internal class DefaultSharedSecretStorage @Inject constructor(
internal class DefaultSharedSecretStorageService @Inject constructor(
private val accountDataService: AccountDataService,
private val coroutineDispatchers: MatrixCoroutineDispatchers,
private val cryptoCoroutineScope: CoroutineScope
@ -51,7 +52,7 @@ internal class DefaultSharedSecretStorage @Inject constructor(
override fun generateKey(keyId: String,
keyName: String,
keySigner: KeySigner,
callback: MatrixCallback<SSSSKeyCreationInfo>) {
callback: MatrixCallback<SsssKeyCreationInfo>) {
cryptoCoroutineScope.launch(coroutineDispatchers.main) {
val pkDecryption = OlmPkDecryption()
val pubKey: String
@ -69,7 +70,7 @@ internal class DefaultSharedSecretStorage @Inject constructor(
val storageKeyContent = SecretStorageKeyContent(
name = keyName,
algorithm = ALGORITHM_CURVE25519_AES_SHA2,
algorithm = SSSS_ALGORITHM_CURVE25519_AES_SHA2,
passphrase = null,
publicKey = pubKey
)
@ -89,7 +90,7 @@ internal class DefaultSharedSecretStorage @Inject constructor(
}
override fun onSuccess(data: Unit) {
callback.onSuccess(SSSSKeyCreationInfo(
callback.onSuccess(SsssKeyCreationInfo(
keyId = keyId,
content = storageKeyContent,
recoveryKey = computeRecoveryKey(privateKey)
@ -105,7 +106,7 @@ internal class DefaultSharedSecretStorage @Inject constructor(
passphrase: String,
keySigner: KeySigner,
progressListener: ProgressListener?,
callback: MatrixCallback<SSSSKeyCreationInfo>) {
callback: MatrixCallback<SsssKeyCreationInfo>) {
cryptoCoroutineScope.launch(coroutineDispatchers.main) {
val privatePart = generatePrivateKeyWithPassword(passphrase, progressListener)
@ -122,7 +123,7 @@ internal class DefaultSharedSecretStorage @Inject constructor(
}
val storageKeyContent = SecretStorageKeyContent(
algorithm = ALGORITHM_CURVE25519_AES_SHA2,
algorithm = SSSS_ALGORITHM_CURVE25519_AES_SHA2,
passphrase = SSSSPassphrase(algorithm = "m.pbkdf2", iterations = privatePart.iterations, salt = privatePart.salt),
publicKey = pubKey
)
@ -142,7 +143,7 @@ internal class DefaultSharedSecretStorage @Inject constructor(
}
override fun onSuccess(data: Unit) {
callback.onSuccess(SSSSKeyCreationInfo(
callback.onSuccess(SsssKeyCreationInfo(
keyId = keyId,
content = storageKeyContent,
recoveryKey = computeRecoveryKey(privatePart.privateKey)
@ -154,11 +155,11 @@ internal class DefaultSharedSecretStorage @Inject constructor(
}
override fun hasKey(keyId: String): Boolean {
return accountDataService.getAccountData("$KEY_ID_BASE.$keyId") != null
return accountDataService.getAccountDataEvent("$KEY_ID_BASE.$keyId") != null
}
override fun getKey(keyId: String): KeyInfoResult {
val accountData = accountDataService.getAccountData("$KEY_ID_BASE.$keyId")
val accountData = accountDataService.getAccountDataEvent("$KEY_ID_BASE.$keyId")
?: return KeyInfoResult.Error(SharedSecretStorageError.UnknownKey(keyId))
return SecretStorageKeyContent.fromJson(accountData.content)?.let {
KeyInfoResult.Success(
@ -180,7 +181,7 @@ internal class DefaultSharedSecretStorage @Inject constructor(
}
override fun getDefaultKey(): KeyInfoResult {
val accountData = accountDataService.getAccountData(DEFAULT_KEY_ID)
val accountData = accountDataService.getAccountDataEvent(DEFAULT_KEY_ID)
?: return KeyInfoResult.Error(SharedSecretStorageError.UnknownKey(DEFAULT_KEY_ID))
val keyId = accountData.content["key"] as? String
?: return KeyInfoResult.Error(SharedSecretStorageError.UnknownKey(DEFAULT_KEY_ID))
@ -196,7 +197,7 @@ internal class DefaultSharedSecretStorage @Inject constructor(
val key = getDefaultKey()
when (key) {
is KeyInfoResult.Success -> {
if (key.keyInfo.content.algorithm == ALGORITHM_CURVE25519_AES_SHA2) {
if (key.keyInfo.content.algorithm == SSSS_ALGORITHM_CURVE25519_AES_SHA2) {
withOlmEncryption { olmEncrypt ->
olmEncrypt.setRecipientKey(key.keyInfo.content.publicKey)
val encryptedResult = olmEncrypt.encrypt(secretBase64)
@ -224,7 +225,7 @@ internal class DefaultSharedSecretStorage @Inject constructor(
val key = getKey(keyId)
when (key) {
is KeyInfoResult.Success -> {
if (key.keyInfo.content.algorithm == ALGORITHM_CURVE25519_AES_SHA2) {
if (key.keyInfo.content.algorithm == SSSS_ALGORITHM_CURVE25519_AES_SHA2) {
withOlmEncryption { olmEncrypt ->
olmEncrypt.setRecipientKey(key.keyInfo.content.publicKey)
val encryptedResult = olmEncrypt.encrypt(secretBase64)
@ -264,7 +265,7 @@ internal class DefaultSharedSecretStorage @Inject constructor(
}
override fun getAlgorithmsForSecret(name: String): List<KeyInfoResult> {
val accountData = accountDataService.getAccountData(name)
val accountData = accountDataService.getAccountDataEvent(name)
?: return listOf(KeyInfoResult.Error(SharedSecretStorageError.UnknownSecret(name)))
val encryptedContent = accountData.content[ENCRYPTED] as? Map<*, *>
?: return listOf(KeyInfoResult.Error(SharedSecretStorageError.SecretNotEncrypted(name)))
@ -279,7 +280,7 @@ internal class DefaultSharedSecretStorage @Inject constructor(
}
override fun getSecret(name: String, keyId: String?, secretKey: SSSSKeySpec, callback: MatrixCallback<String>) {
val accountData = accountDataService.getAccountData(name) ?: return Unit.also {
val accountData = accountDataService.getAccountDataEvent(name) ?: return Unit.also {
callback.onFailure(SharedSecretStorageError.UnknownSecret(name))
}
val encryptedContent = accountData.content[ENCRYPTED] as? Map<*, *> ?: return Unit.also {
@ -299,7 +300,7 @@ internal class DefaultSharedSecretStorage @Inject constructor(
}
val algorithm = key.keyInfo.content
if (ALGORITHM_CURVE25519_AES_SHA2 == algorithm.algorithm) {
if (SSSS_ALGORITHM_CURVE25519_AES_SHA2 == algorithm.algorithm) {
val keySpec = secretKey as? Curve25519AesSha2KeySpec ?: return Unit.also {
callback.onFailure(SharedSecretStorageError.BadKeyFormat)
}
@ -332,8 +333,6 @@ internal class DefaultSharedSecretStorage @Inject constructor(
const val ENCRYPTED = "encrypted"
const val DEFAULT_KEY_ID = "m.secret_storage.default_key"
const val ALGORITHM_CURVE25519_AES_SHA2 = "m.secret_storage.v1.curve25519-aes-sha2"
fun withOlmEncryption(block: (OlmPkEncryption) -> Unit) {
val olmPkEncryption = OlmPkEncryption()
try {

View File

@ -20,9 +20,10 @@ import io.realm.RealmObject
import io.realm.annotations.Index
/**
* Clients can store custom config data for their account on their homeserver.
* Clients can store custom config data for their account on their HomeServer.
* This account data will be synced between different devices and can persist across installations on a particular device.
* Users may only view the account data for their own accountThe account_data may be either global or scoped to a particular rooms.
* Users may only view the account data for their own account.
* The account_data may be either global or scoped to a particular rooms.
*/
internal open class UserAccountDataEntity(
@Index var type: String? = null,

View File

@ -1,28 +0,0 @@
/*
* Copyright (c) 2020 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package im.vector.matrix.android.internal.network.parsing
import com.squareup.moshi.JsonAdapter
import com.squareup.moshi.Moshi
import java.lang.reflect.Type
class AccountDataJsonAdapterFactory<UserAccountData> : JsonAdapter.Factory {
override fun create(type: Type, annotations: MutableSet<out Annotation>, moshi: Moshi): JsonAdapter<*>? {
TODO("not implemented") // To change body of created functions use File | Settings | File Templates.
}
}

View File

@ -36,7 +36,7 @@ import im.vector.matrix.android.api.session.accountdata.AccountDataService
import im.vector.matrix.android.api.session.homeserver.HomeServerCapabilitiesService
import im.vector.matrix.android.api.session.securestorage.SecureStorageService
import im.vector.matrix.android.api.session.securestorage.SharedSecretStorageService
import im.vector.matrix.android.internal.crypto.secrets.DefaultSharedSecretStorage
import im.vector.matrix.android.internal.crypto.secrets.DefaultSharedSecretStorageService
import im.vector.matrix.android.internal.crypto.verification.VerificationMessageLiveObserver
import im.vector.matrix.android.internal.database.LiveEntityObserver
import im.vector.matrix.android.internal.database.SessionRealmConfigurationFactory
@ -269,8 +269,8 @@ internal abstract class SessionModule {
abstract fun bindHomeServerCapabilitiesService(homeServerCapabilitiesService: DefaultHomeServerCapabilitiesService): HomeServerCapabilitiesService
@Binds
abstract fun bindAccountDataServiceService(accountDataService: DefaultAccountDataService): AccountDataService
abstract fun bindAccountDataService(accountDataService: DefaultAccountDataService): AccountDataService
@Binds
abstract fun bindSharedSecuredSecretStorageService(service: DefaultSharedSecretStorage): SharedSecretStorageService
abstract fun bindSharedSecretStorageService(service: DefaultSharedSecretStorageService): SharedSecretStorageService
}

View File

@ -46,17 +46,17 @@ internal class DefaultAccountDataService @Inject constructor(
private val moshi = MoshiProvider.providesMoshi()
private val adapter = moshi.adapter<Map<String, Any>>(JSON_DICT_PARAMETERIZED_TYPE)
override fun getAccountData(type: String): UserAccountDataEvent? {
return getAccountData(listOf(type)).firstOrNull()
override fun getAccountDataEvent(type: String): UserAccountDataEvent? {
return getAccountDataEvents(listOf(type)).firstOrNull()
}
override fun getLiveAccountData(type: String): LiveData<Optional<UserAccountDataEvent>> {
return Transformations.map(getLiveAccountData(listOf(type))) {
override fun getLiveAccountDataEvent(type: String): LiveData<Optional<UserAccountDataEvent>> {
return Transformations.map(getLiveAccountDataEvents(listOf(type))) {
it.firstOrNull()?.toOptional()
}
}
override fun getAccountData(filterType: List<String>): List<UserAccountDataEvent> {
override fun getAccountDataEvents(filterType: List<String>): List<UserAccountDataEvent> {
return monarchy.fetchAllCopiedSync { realm ->
realm.where(UserAccountDataEntity::class.java)
.apply {
@ -74,7 +74,7 @@ internal class DefaultAccountDataService @Inject constructor(
} ?: emptyList()
}
override fun getLiveAccountData(filterType: List<String>): LiveData<List<UserAccountDataEvent>> {
override fun getLiveAccountDataEvents(filterType: List<String>): LiveData<List<UserAccountDataEvent>> {
return monarchy.findAllMappedWithChanges({ realm ->
realm.where(UserAccountDataEntity::class.java)
.apply {

View File

@ -24,6 +24,7 @@ import im.vector.matrix.android.internal.di.MoshiProvider
import im.vector.matrix.android.internal.session.sync.model.accountdata.UserAccountData
import im.vector.matrix.android.internal.session.sync.model.accountdata.UserAccountDataEvent
import im.vector.riotx.R
import im.vector.riotx.core.extensions.cleanup
import im.vector.riotx.core.extensions.configureWith
import im.vector.riotx.core.platform.VectorBaseActivity
import im.vector.riotx.core.platform.VectorBaseFragment
@ -58,6 +59,12 @@ class AccountDataFragment @Inject constructor(
epoxyController.interactionListener = this
}
override fun onDestroyView() {
super.onDestroyView()
recyclerView.cleanup()
epoxyController.interactionListener = null
}
override fun didTap(data: UserAccountData) {
val fb = data as? UserAccountDataEvent ?: return
val jsonString = MoshiProvider.providesMoshi()