mirror of
https://github.com/element-hq/element-android
synced 2024-11-24 18:35:40 +03:00
Fix / cross signing info live data not always updated
This commit is contained in:
parent
ea6e8a6789
commit
83e44ac96e
7 changed files with 151 additions and 141 deletions
|
@ -877,10 +877,10 @@ internal class RealmCryptoStore(private val realmConfiguration: RealmConfigurati
|
|||
}
|
||||
|
||||
override fun setMyCrossSigningInfo(info: MXCrossSigningInfo?) {
|
||||
doRealmQueryAndCopy(realmConfiguration) {
|
||||
it.where<CryptoMetadataEntity>().findFirst()
|
||||
}?.userId?.let {
|
||||
setCrossSigningInfo(it, info)
|
||||
doRealmTransaction(realmConfiguration) { realm ->
|
||||
realm.where<CryptoMetadataEntity>().findFirst()?.userId?.let { userId ->
|
||||
addOrUpdateCrossSigningInfo(realm, userId, info)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -998,31 +998,36 @@ internal class RealmCryptoStore(private val realmConfiguration: RealmConfigurati
|
|||
|
||||
override fun setCrossSigningInfo(userId: String, info: MXCrossSigningInfo?) {
|
||||
doRealmTransaction(realmConfiguration) { realm ->
|
||||
|
||||
var existing = CrossSigningInfoEntity.get(realm, userId)
|
||||
if (info == null) {
|
||||
// Delete known if needed
|
||||
existing?.deleteFromRealm()
|
||||
// TODO notify, we might need to untrust things?
|
||||
} else {
|
||||
// Just override existing, caller should check and untrust id needed
|
||||
existing = CrossSigningInfoEntity.getOrCreate(realm, userId)
|
||||
val xkeys = RealmList<KeyInfoEntity>()
|
||||
info.crossSigningKeys.forEach { info ->
|
||||
xkeys.add(
|
||||
realm.createObject(KeyInfoEntity::class.java).also { keyInfoEntity ->
|
||||
keyInfoEntity.publicKeyBase64 = info.unpaddedBase64PublicKey
|
||||
keyInfoEntity.usages = info.usages?.let { RealmList(*it.toTypedArray()) }
|
||||
?: RealmList()
|
||||
keyInfoEntity.putSignatures(info.signatures)
|
||||
// TODO how to handle better, check if same keys?
|
||||
// reset trust
|
||||
keyInfoEntity.trustLevelEntity = null
|
||||
}
|
||||
)
|
||||
}
|
||||
existing.crossSigningKeys = xkeys
|
||||
}
|
||||
addOrUpdateCrossSigningInfo(realm, userId, info)
|
||||
}
|
||||
}
|
||||
|
||||
private fun addOrUpdateCrossSigningInfo(realm: Realm, userId: String, info: MXCrossSigningInfo?): CrossSigningInfoEntity? {
|
||||
var existing = CrossSigningInfoEntity.get(realm, userId)
|
||||
if (info == null) {
|
||||
// Delete known if needed
|
||||
existing?.deleteFromRealm()
|
||||
// TODO notify, we might need to untrust things?
|
||||
} else {
|
||||
// Just override existing, caller should check and untrust id needed
|
||||
existing = CrossSigningInfoEntity.getOrCreate(realm, userId)
|
||||
// existing.crossSigningKeys.forEach { it.deleteFromRealm() }
|
||||
val xkeys = RealmList<KeyInfoEntity>()
|
||||
info.crossSigningKeys.forEach { cryptoCrossSigningKey ->
|
||||
xkeys.add(
|
||||
realm.createObject(KeyInfoEntity::class.java).also { keyInfoEntity ->
|
||||
keyInfoEntity.publicKeyBase64 = cryptoCrossSigningKey.unpaddedBase64PublicKey
|
||||
keyInfoEntity.usages = cryptoCrossSigningKey.usages?.let { RealmList(*it.toTypedArray()) }
|
||||
?: RealmList()
|
||||
keyInfoEntity.putSignatures(cryptoCrossSigningKey.signatures)
|
||||
// TODO how to handle better, check if same keys?
|
||||
// reset trust
|
||||
keyInfoEntity.trustLevelEntity = null
|
||||
}
|
||||
)
|
||||
}
|
||||
existing.crossSigningKeys = xkeys
|
||||
}
|
||||
return existing
|
||||
}
|
||||
}
|
||||
|
|
|
@ -46,7 +46,6 @@ import im.vector.matrix.rx.mapOptional
|
|||
import im.vector.matrix.rx.rx
|
||||
import im.vector.matrix.rx.unwrap
|
||||
import im.vector.riotx.R
|
||||
import im.vector.riotx.core.di.HasScreenInjector
|
||||
import im.vector.riotx.core.platform.VectorViewModel
|
||||
import im.vector.riotx.core.resources.StringProvider
|
||||
import im.vector.riotx.core.utils.DataSource
|
||||
|
@ -75,7 +74,6 @@ class RoomMemberProfileViewModel @AssistedInject constructor(@Assisted private v
|
|||
val fragment: RoomMemberProfileFragment = (viewModelContext as FragmentViewModelContext).fragment()
|
||||
return fragment.viewModelFactory.create(state)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private val _viewEvents = PublishDataSource<RoomMemberProfileViewEvents>()
|
||||
|
@ -118,11 +116,8 @@ class RoomMemberProfileViewModel @AssistedInject constructor(@Assisted private v
|
|||
}
|
||||
|
||||
session.rx().liveCrossSigningInfo(initialState.userId)
|
||||
.map {
|
||||
it.getOrNull()
|
||||
}
|
||||
.execute {
|
||||
copy(userMXCrossSigningInfo = it)
|
||||
copy(userMXCrossSigningInfo = it.invoke()?.getOrNull())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -150,7 +145,7 @@ class RoomMemberProfileViewModel @AssistedInject constructor(@Assisted private v
|
|||
private fun prepareVerification(action: RoomMemberProfileAction.VerifyUser) = withState { state ->
|
||||
// Sanity
|
||||
if (state.isRoomEncrypted) {
|
||||
if (!state.isMine && state.userMXCrossSigningInfo.invoke()?.isTrusted() == false) {
|
||||
if (!state.isMine && state.userMXCrossSigningInfo?.isTrusted() == false) {
|
||||
// ok, let's find or create the DM room
|
||||
_actionResultLiveData.postValue(
|
||||
LiveEvent(Success(action.copy(userId = state.userId)))
|
||||
|
|
|
@ -35,7 +35,7 @@ data class RoomMemberProfileViewState(
|
|||
val powerLevelsContent: Async<PowerLevelsContent> = Uninitialized,
|
||||
val userPowerLevelString: Async<String> = Uninitialized,
|
||||
val userMatrixItem: Async<MatrixItem> = Uninitialized,
|
||||
val userMXCrossSigningInfo: Async<MXCrossSigningInfo?> = Uninitialized,
|
||||
val userMXCrossSigningInfo: MXCrossSigningInfo? = null,
|
||||
val allDevicesAreTrusted: Async<Boolean> = Uninitialized
|
||||
) : MvRxState {
|
||||
|
||||
|
|
|
@ -74,11 +74,8 @@ class DeviceListBottomSheetViewModel @AssistedInject constructor(@Assisted priva
|
|||
}
|
||||
|
||||
session.rx().liveCrossSigningInfo(userId)
|
||||
.map {
|
||||
it.getOrNull()
|
||||
}
|
||||
.execute {
|
||||
copy(memberCrossSigningKey = it.invoke())
|
||||
copy(memberCrossSigningKey = it.invoke()?.getOrNull())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -105,6 +105,7 @@ class VectorSettingsSecurityPrivacyFragment @Inject constructor(
|
|||
super.onResume()
|
||||
// My device name may have been updated
|
||||
refreshMyDevice()
|
||||
refreshXSigningStatus()
|
||||
mCryptographyCategory.isVisible = vectorPreferences.developerMode()
|
||||
}
|
||||
|
||||
|
@ -128,6 +129,10 @@ class VectorSettingsSecurityPrivacyFragment @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
refreshXSigningStatus()
|
||||
}
|
||||
|
||||
private fun refreshXSigningStatus() {
|
||||
if (vectorPreferences.developerMode()) {
|
||||
val crossSigningKeys = session.getCrossSigningService().getMyCrossSigningKeys()
|
||||
val xSigningIsEnableInAccount = crossSigningKeys != null
|
||||
|
|
|
@ -16,8 +16,6 @@
|
|||
package im.vector.riotx.features.settings.crosssigning
|
||||
|
||||
import com.airbnb.epoxy.TypedEpoxyController
|
||||
import com.airbnb.mvrx.Loading
|
||||
import com.airbnb.mvrx.Success
|
||||
import im.vector.riotx.R
|
||||
import im.vector.riotx.core.epoxy.loadingItem
|
||||
import im.vector.riotx.core.resources.ColorProvider
|
||||
|
@ -50,14 +48,16 @@ class CrossSigningEpoxyController @Inject constructor(
|
|||
titleIconResourceId(R.drawable.ic_shield_trusted)
|
||||
title(stringProvider.getString(R.string.encryption_information_dg_xsigning_complete))
|
||||
}
|
||||
bottomSheetVerificationActionItem {
|
||||
id("resetkeys")
|
||||
title("Reset keys")
|
||||
titleColor(colorProvider.getColor(R.color.riotx_destructive_accent))
|
||||
iconRes(R.drawable.ic_arrow_right)
|
||||
iconColor(colorProvider.getColor(R.color.riotx_destructive_accent))
|
||||
listener {
|
||||
interactionListener?.onResetCrossSigningKeys()
|
||||
if (!data.isUploadingKeys) {
|
||||
bottomSheetVerificationActionItem {
|
||||
id("resetkeys")
|
||||
title("Reset keys")
|
||||
titleColor(colorProvider.getColor(R.color.riotx_destructive_accent))
|
||||
iconRes(R.drawable.ic_arrow_right)
|
||||
iconColor(colorProvider.getColor(R.color.riotx_destructive_accent))
|
||||
listener {
|
||||
interactionListener?.onResetCrossSigningKeys()
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (data.xSigningKeysAreTrusted) {
|
||||
|
@ -66,30 +66,32 @@ class CrossSigningEpoxyController @Inject constructor(
|
|||
titleIconResourceId(R.drawable.ic_shield_warning)
|
||||
title(stringProvider.getString(R.string.encryption_information_dg_xsigning_trusted))
|
||||
}
|
||||
bottomSheetVerificationActionItem {
|
||||
id("resetkeys")
|
||||
title("Reset keys")
|
||||
titleColor(colorProvider.getColor(R.color.riotx_destructive_accent))
|
||||
iconRes(R.drawable.ic_arrow_right)
|
||||
iconColor(colorProvider.getColor(R.color.riotx_destructive_accent))
|
||||
listener {
|
||||
interactionListener?.onResetCrossSigningKeys()
|
||||
if (!data.isUploadingKeys) {
|
||||
bottomSheetVerificationActionItem {
|
||||
id("resetkeys")
|
||||
title("Reset keys")
|
||||
titleColor(colorProvider.getColor(R.color.riotx_destructive_accent))
|
||||
iconRes(R.drawable.ic_arrow_right)
|
||||
iconColor(colorProvider.getColor(R.color.riotx_destructive_accent))
|
||||
listener {
|
||||
interactionListener?.onResetCrossSigningKeys()
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (data.xSigningIsEnableInAccount) {
|
||||
genericItem {
|
||||
id("enable")
|
||||
titleIconResourceId(R.drawable.ic_shield_black)
|
||||
title(stringProvider.getString(R.string.encryption_information_dg_xsigning_not_trusted))
|
||||
}
|
||||
bottomSheetVerificationActionItem {
|
||||
id("resetkeys")
|
||||
title("Reset keys")
|
||||
titleColor(colorProvider.getColor(R.color.riotx_destructive_accent))
|
||||
iconRes(R.drawable.ic_arrow_right)
|
||||
iconColor(colorProvider.getColor(R.color.riotx_destructive_accent))
|
||||
listener {
|
||||
interactionListener?.onResetCrossSigningKeys()
|
||||
} else if (data.xSigningIsEnableInAccount) {
|
||||
genericItem {
|
||||
id("enable")
|
||||
titleIconResourceId(R.drawable.ic_shield_black)
|
||||
title(stringProvider.getString(R.string.encryption_information_dg_xsigning_not_trusted))
|
||||
}
|
||||
bottomSheetVerificationActionItem {
|
||||
id("resetkeys")
|
||||
title("Reset keys")
|
||||
titleColor(colorProvider.getColor(R.color.riotx_destructive_accent))
|
||||
iconRes(R.drawable.ic_arrow_right)
|
||||
iconColor(colorProvider.getColor(R.color.riotx_destructive_accent))
|
||||
listener {
|
||||
interactionListener?.onResetCrossSigningKeys()
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -97,75 +99,74 @@ class CrossSigningEpoxyController @Inject constructor(
|
|||
id("not")
|
||||
title(stringProvider.getString(R.string.encryption_information_dg_xsigning_disabled))
|
||||
}
|
||||
|
||||
bottomSheetVerificationActionItem {
|
||||
id("initKeys")
|
||||
title("Initialize keys")
|
||||
titleColor(colorProvider.getColor(R.color.riotx_positive_accent))
|
||||
iconRes(R.drawable.ic_arrow_right)
|
||||
iconColor(colorProvider.getColor(R.color.riotx_positive_accent))
|
||||
listener {
|
||||
interactionListener?.onInitializeCrossSigningKeys()
|
||||
if (!data.isUploadingKeys) {
|
||||
bottomSheetVerificationActionItem {
|
||||
id("initKeys")
|
||||
title("Initialize keys")
|
||||
titleColor(colorProvider.getColor(R.color.riotx_positive_accent))
|
||||
iconRes(R.drawable.ic_arrow_right)
|
||||
iconColor(colorProvider.getColor(R.color.riotx_positive_accent))
|
||||
listener {
|
||||
interactionListener?.onInitializeCrossSigningKeys()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
when (data.crossSigningInfo) {
|
||||
is Loading -> {
|
||||
loadingItem {
|
||||
id("loading")
|
||||
if (data.isUploadingKeys) {
|
||||
loadingItem {
|
||||
id("loading")
|
||||
}
|
||||
} else {
|
||||
|
||||
val crossSigningKeys = data.crossSigningInfo
|
||||
|
||||
crossSigningKeys?.masterKey()?.let {
|
||||
genericItemWithValue {
|
||||
id("msk")
|
||||
titleIconResourceId(R.drawable.key_small)
|
||||
title(
|
||||
span {
|
||||
+"Master Key:\n"
|
||||
span {
|
||||
text = it.unpaddedBase64PublicKey ?: ""
|
||||
textColor = colorProvider.getColorFromAttribute(R.attr.riotx_text_secondary)
|
||||
textSize = dimensionConverter.spToPx(12)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
is Success -> {
|
||||
val crossSigningKeys = data.crossSigningInfo.invoke()
|
||||
|
||||
crossSigningKeys?.masterKey()?.let {
|
||||
genericItemWithValue {
|
||||
id("msk")
|
||||
titleIconResourceId(R.drawable.key_small)
|
||||
title(
|
||||
crossSigningKeys?.userKey()?.let {
|
||||
genericItemWithValue {
|
||||
id("usk")
|
||||
titleIconResourceId(R.drawable.key_small)
|
||||
title(
|
||||
span {
|
||||
+"User Key:\n"
|
||||
span {
|
||||
+"Master Key:\n"
|
||||
span {
|
||||
text = it.unpaddedBase64PublicKey ?: ""
|
||||
textColor = colorProvider.getColorFromAttribute(R.attr.riotx_text_secondary)
|
||||
textSize = dimensionConverter.spToPx(12)
|
||||
}
|
||||
text = it.unpaddedBase64PublicKey ?: ""
|
||||
textColor = colorProvider.getColorFromAttribute(R.attr.riotx_text_secondary)
|
||||
textSize = dimensionConverter.spToPx(12)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
crossSigningKeys?.userKey()?.let {
|
||||
genericItemWithValue {
|
||||
id("usk")
|
||||
titleIconResourceId(R.drawable.key_small)
|
||||
title(
|
||||
}
|
||||
crossSigningKeys?.selfSigningKey()?.let {
|
||||
genericItemWithValue {
|
||||
id("ssk")
|
||||
titleIconResourceId(R.drawable.key_small)
|
||||
title(
|
||||
span {
|
||||
+"Self Signed Key:\n"
|
||||
span {
|
||||
+"User Key:\n"
|
||||
span {
|
||||
text = it.unpaddedBase64PublicKey ?: ""
|
||||
textColor = colorProvider.getColorFromAttribute(R.attr.riotx_text_secondary)
|
||||
textSize = dimensionConverter.spToPx(12)
|
||||
}
|
||||
text = it.unpaddedBase64PublicKey ?: ""
|
||||
textColor = colorProvider.getColorFromAttribute(R.attr.riotx_text_secondary)
|
||||
textSize = dimensionConverter.spToPx(12)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
crossSigningKeys?.selfSigningKey()?.let {
|
||||
genericItemWithValue {
|
||||
id("ssk")
|
||||
titleIconResourceId(R.drawable.key_small)
|
||||
title(
|
||||
span {
|
||||
+"Self Signed Key:\n"
|
||||
span {
|
||||
text = it.unpaddedBase64PublicKey ?: ""
|
||||
textColor = colorProvider.getColorFromAttribute(R.attr.riotx_text_secondary)
|
||||
textSize = dimensionConverter.spToPx(12)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,7 +20,6 @@ import androidx.lifecycle.MutableLiveData
|
|||
import com.airbnb.mvrx.Async
|
||||
import com.airbnb.mvrx.Fail
|
||||
import com.airbnb.mvrx.FragmentViewModelContext
|
||||
import com.airbnb.mvrx.Loading
|
||||
import com.airbnb.mvrx.MvRxState
|
||||
import com.airbnb.mvrx.MvRxViewModelFactory
|
||||
import com.airbnb.mvrx.Success
|
||||
|
@ -44,10 +43,11 @@ import im.vector.riotx.core.resources.StringProvider
|
|||
import im.vector.riotx.core.utils.LiveEvent
|
||||
|
||||
data class CrossSigningSettingsViewState(
|
||||
val crossSigningInfo: Async<MXCrossSigningInfo?> = Uninitialized,
|
||||
val crossSigningInfo: MXCrossSigningInfo? = null,
|
||||
val xSigningIsEnableInAccount: Boolean = false,
|
||||
val xSigningKeysAreTrusted: Boolean = false,
|
||||
val xSigningKeyCanSign: Boolean = true
|
||||
val xSigningKeyCanSign: Boolean = true,
|
||||
val isUploadingKeys: Boolean = false
|
||||
) : MvRxState
|
||||
|
||||
sealed class CrossSigningAction : VectorViewModelAction {
|
||||
|
@ -67,16 +67,13 @@ class CrossSigningSettingsViewModel @AssistedInject constructor(@Assisted privat
|
|||
|
||||
init {
|
||||
session.rx().liveCrossSigningInfo(session.myUserId)
|
||||
.map {
|
||||
it.getOrNull()
|
||||
}
|
||||
.execute {
|
||||
val crossSigningKeys = it.invoke()
|
||||
val crossSigningKeys = it.invoke()?.getOrNull()
|
||||
val xSigningIsEnableInAccount = crossSigningKeys != null
|
||||
val xSigningKeysAreTrusted = session.getCrossSigningService().checkUserTrust(session.myUserId).isVerified()
|
||||
val xSigningKeyCanSign = session.getCrossSigningService().canCrossSign()
|
||||
copy(
|
||||
crossSigningInfo = it,
|
||||
crossSigningInfo = crossSigningKeys,
|
||||
xSigningIsEnableInAccount = xSigningIsEnableInAccount,
|
||||
xSigningKeysAreTrusted = xSigningKeysAreTrusted,
|
||||
xSigningKeyCanSign = xSigningKeyCanSign
|
||||
|
@ -99,9 +96,16 @@ class CrossSigningSettingsViewModel @AssistedInject constructor(@Assisted privat
|
|||
|
||||
private fun initializeCrossSigning(auth: UserPasswordAuth?) {
|
||||
setState {
|
||||
copy(crossSigningInfo = Loading())
|
||||
copy(isUploadingKeys = true)
|
||||
}
|
||||
session.getCrossSigningService().initializeCrossSigning(auth, object : MatrixCallback<Unit> {
|
||||
|
||||
override fun onSuccess(data: Unit) {
|
||||
setState {
|
||||
copy(isUploadingKeys = false)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onFailure(failure: Throwable) {
|
||||
if (failure is Failure.OtherServerError
|
||||
&& failure.httpCode == 401
|
||||
|
@ -125,6 +129,9 @@ class CrossSigningSettingsViewModel @AssistedInject constructor(@Assisted privat
|
|||
}
|
||||
}
|
||||
_requestLiveData.postValue(LiveEvent(Fail(Throwable("You cannot do that from mobile"))))
|
||||
setState {
|
||||
copy(isUploadingKeys = false)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue