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 ✨:
- Enable encryption in unencrypted rooms, from the room settings (#212)
- Negotiate E2E by default for DMs (#907)
Improvements 🙌:
- 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")
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.
*
* @param algorithm the algorithm
*/
fun enableEncryptionWithAlgorithm(algorithm: String): CreateRoomParams {
fun enableEncryptionWithAlgorithm(algorithm: String = MXCRYPTO_ALGORITHM_MEGOLM): CreateRoomParams {
return if (algorithm == MXCRYPTO_ALGORITHM_MEGOLM) {
val contentMap = mapOf("algorithm" to algorithm)

View File

@ -17,9 +17,12 @@
package im.vector.matrix.android.internal.session.room.create
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.model.create.CreateRoomParams
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.model.RoomEntity
import im.vector.matrix.android.internal.database.model.RoomEntityFields
@ -49,12 +52,41 @@ internal class DefaultCreateRoomTask @Inject constructor(
private val readMarkersTask: SetReadMarkersTask,
@SessionDatabase
private val realmConfiguration: RealmConfiguration,
private val crossSigningService: CrossSigningService,
private val deviceListManager: DeviceListManager,
private val eventBus: EventBus
) : CreateRoomTask {
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) {
apiCall = roomAPI.createRoom(params)
apiCall = roomAPI.createRoom(createRoomParams)
}
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)
@ -66,8 +98,8 @@ internal class DefaultCreateRoomTask @Inject constructor(
} catch (exception: TimeoutCancellationException) {
throw CreateRoomFailure.CreatedWithTimeout
}
if (params.isDirect()) {
handleDirectChatCreation(params, roomId)
if (createRoomParams.isDirect()) {
handleDirectChatCreation(createRoomParams, roomId)
}
setReadMarkers(roomId)
return roomId

View File

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

View File

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