Negotiate E2E by default for DMs (#907)

This commit is contained in:
Benoit Marty 2020-01-29 16:11:23 +01:00
parent 237da5bb16
commit ae36846aaf
6 changed files with 74 additions and 12 deletions

View file

@ -3,6 +3,7 @@ Changes in RiotX 0.14.0 (2020-XX-XX)
Features ✨: Features ✨:
- Enable encryption in unencrypted rooms, from the room settings (#212) - Enable encryption in unencrypted rooms, from the room settings (#212)
- Negotiate E2E by default for DMs (#907)
Improvements 🙌: Improvements 🙌:
- Sharing things to RiotX: sort list by recent room first (#771) - Sharing things to RiotX: sort list by recent room first (#771)

View file

@ -0,0 +1,22 @@
/*
* 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.
* 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.api.extensions
fun Boolean?.orTrue() = this ?: true
fun Boolean?.orFalse() = this ?: false

View file

@ -120,12 +120,19 @@ data class CreateRoomParams(
@Json(name = "power_level_content_override") @Json(name = "power_level_content_override")
val powerLevelContentOverride: PowerLevelsContent? = null val powerLevelContentOverride: PowerLevelsContent? = null
) { ) {
/**
* Set to true means that if cross-signing is enabled and we can get keys for every invited users,
* the encryption will be enabled on the created room
*/
@Transient
var enableEncryptionIfInvitedUsersSupportIt: Boolean = false
/** /**
* Add the crypto algorithm to the room creation parameters. * Add the crypto algorithm to the room creation parameters.
* *
* @param algorithm the algorithm * @param algorithm the algorithm
*/ */
fun enableEncryptionWithAlgorithm(algorithm: String): CreateRoomParams { fun enableEncryptionWithAlgorithm(algorithm: String = MXCRYPTO_ALGORITHM_MEGOLM): CreateRoomParams {
return if (algorithm == MXCRYPTO_ALGORITHM_MEGOLM) { return if (algorithm == MXCRYPTO_ALGORITHM_MEGOLM) {
val contentMap = mapOf("algorithm" to algorithm) val contentMap = mapOf("algorithm" to algorithm)

View file

@ -17,9 +17,12 @@
package im.vector.matrix.android.internal.session.room.create package im.vector.matrix.android.internal.session.room.create
import com.zhuinden.monarchy.Monarchy import com.zhuinden.monarchy.Monarchy
import im.vector.matrix.android.api.extensions.orTrue
import im.vector.matrix.android.api.session.crypto.crosssigning.CrossSigningService
import im.vector.matrix.android.api.session.room.failure.CreateRoomFailure import im.vector.matrix.android.api.session.room.failure.CreateRoomFailure
import im.vector.matrix.android.api.session.room.model.create.CreateRoomParams import im.vector.matrix.android.api.session.room.model.create.CreateRoomParams
import im.vector.matrix.android.api.session.room.model.create.CreateRoomResponse import im.vector.matrix.android.api.session.room.model.create.CreateRoomResponse
import im.vector.matrix.android.internal.crypto.DeviceListManager
import im.vector.matrix.android.internal.database.awaitNotEmptyResult import im.vector.matrix.android.internal.database.awaitNotEmptyResult
import im.vector.matrix.android.internal.database.model.RoomEntity import im.vector.matrix.android.internal.database.model.RoomEntity
import im.vector.matrix.android.internal.database.model.RoomEntityFields import im.vector.matrix.android.internal.database.model.RoomEntityFields
@ -49,12 +52,41 @@ internal class DefaultCreateRoomTask @Inject constructor(
private val readMarkersTask: SetReadMarkersTask, private val readMarkersTask: SetReadMarkersTask,
@SessionDatabase @SessionDatabase
private val realmConfiguration: RealmConfiguration, private val realmConfiguration: RealmConfiguration,
private val crossSigningService: CrossSigningService,
private val deviceListManager: DeviceListManager,
private val eventBus: EventBus private val eventBus: EventBus
) : CreateRoomTask { ) : CreateRoomTask {
override suspend fun execute(params: CreateRoomParams): String { override suspend fun execute(params: CreateRoomParams): String {
val createRoomParams = params
.takeIf { it.enableEncryptionIfInvitedUsersSupportIt }
.takeIf { crossSigningService.isCrossSigningEnabled() }
?.takeIf { it.invite3pids.isNullOrEmpty() }
?.invitedUserIds
?.let { userIds ->
val keys = deviceListManager.downloadKeys(userIds, forceDownload = false)
userIds.any { userId ->
if (keys.map[userId].isNullOrEmpty()) {
// A user has no device, so do not enable encryption
true
} else {
// Check that every user's device have at least one key
keys.map[userId]?.values?.any { it.keys.isNullOrEmpty() } ?: true
}
}
}
.orTrue()
.let { cannotEnableEncryption ->
if (!cannotEnableEncryption) {
params.enableEncryptionWithAlgorithm()
} else {
params
}
}
val createRoomResponse = executeRequest<CreateRoomResponse>(eventBus) { val createRoomResponse = executeRequest<CreateRoomResponse>(eventBus) {
apiCall = roomAPI.createRoom(params) apiCall = roomAPI.createRoom(createRoomParams)
} }
val roomId = createRoomResponse.roomId!! val roomId = createRoomResponse.roomId!!
// Wait for room to come back from the sync (but it can maybe be in the DB if the sync response is received before) // Wait for room to come back from the sync (but it can maybe be in the DB if the sync response is received before)
@ -66,8 +98,8 @@ internal class DefaultCreateRoomTask @Inject constructor(
} catch (exception: TimeoutCancellationException) { } catch (exception: TimeoutCancellationException) {
throw CreateRoomFailure.CreatedWithTimeout throw CreateRoomFailure.CreatedWithTimeout
} }
if (params.isDirect()) { if (createRoomParams.isDirect()) {
handleDirectChatCreation(params, roomId) handleDirectChatCreation(createRoomParams, roomId)
} }
setReadMarkers(roomId) setReadMarkers(roomId)
return roomId return roomId

View file

@ -92,14 +92,12 @@ class CreateDirectRoomViewModel @AssistedInject constructor(@Assisted
} }
private fun createRoomAndInviteSelectedUsers() = withState { currentState -> private fun createRoomAndInviteSelectedUsers() = withState { currentState ->
val isDirect = currentState.selectedUsers.size == 1
val roomParams = CreateRoomParams( val roomParams = CreateRoomParams(
invitedUserIds = ArrayList(currentState.selectedUsers.map { it.userId }) invitedUserIds = currentState.selectedUsers.map { it.userId }
).apply { )
if (isDirect) { .setDirectMessage()
setDirectMessage() .also { it.enableEncryptionIfInvitedUsersSupportIt = true }
}
}
session.rx() session.rx()
.createRoom(roomParams) .createRoom(roomParams)
.execute { .execute {

View file

@ -128,9 +128,11 @@ class VerificationBottomSheetViewModel @AssistedInject constructor(@Assisted ini
) )
} }
val roomParams = CreateRoomParams( val roomParams = CreateRoomParams(
invitedUserIds = listOf(otherUserId).toMutableList() invitedUserIds = listOf(otherUserId)
) )
.setDirectMessage() .setDirectMessage()
.also { it.enableEncryptionIfInvitedUsersSupportIt = true }
session.createRoom(roomParams, object : MatrixCallback<String> { session.createRoom(roomParams, object : MatrixCallback<String> {
override fun onSuccess(data: String) { override fun onSuccess(data: String) {
setState { setState {