From 3ceac70536d515231551361118792783bfcf1a79 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 7 Jan 2020 18:37:05 +0100 Subject: [PATCH] Enable encryption on a room, SDK part (#212) --- CHANGES.md | 1 + .../api/session/events/model/EventType.kt | 2 +- .../session/room/crypto/RoomCryptoService.kt | 4 +++ .../room/model/create/CreateRoomParams.kt | 2 +- .../api/session/room/state/StateService.kt | 5 ++++ .../internal/crypto/DefaultCryptoService.kt | 6 ++-- .../internal/session/room/DefaultRoom.kt | 11 +++++++- .../session/room/RoomSummaryUpdater.kt | 2 +- .../session/room/state/DefaultStateService.kt | 28 ++++++++++++++++--- .../timeline/factory/EncryptionItemFactory.kt | 2 +- .../timeline/factory/TimelineItemFactory.kt | 2 +- .../helper/TimelineDisplayableEvents.kt | 2 +- 12 files changed, 53 insertions(+), 14 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 0b0666e754..3741f69426 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -13,6 +13,7 @@ Improvements 🙌: - Add settings for rageshake sensibility - Fix autocompletion issues and add support for rooms, groups, and emoji (#780) - Show skip to bottom FAB while scrolling down (#752) + - Enable encryption on a room, SDK part (#212) Other changes: - Change the way RiotX identifies a session to allow the SDK to support several sessions with the same user (#800) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/events/model/EventType.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/events/model/EventType.kt index 22bf564a8a..903df0cace 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/events/model/EventType.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/events/model/EventType.kt @@ -25,7 +25,6 @@ object EventType { const val MESSAGE = "m.room.message" const val STICKER = "m.sticker" const val ENCRYPTED = "m.room.encrypted" - const val ENCRYPTION = "m.room.encryption" const val FEEDBACK = "m.room.message.feedback" const val TYPING = "m.typing" const val REDACTION = "m.room.redaction" @@ -54,6 +53,7 @@ object EventType { const val STATE_ROOM_HISTORY_VISIBILITY = "m.room.history_visibility" const val STATE_ROOM_RELATED_GROUPS = "m.room.related_groups" const val STATE_ROOM_PINNED_EVENT = "m.room.pinned_events" + const val STATE_ROOM_ENCRYPTION = "m.room.encryption" // Call Events diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/crypto/RoomCryptoService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/crypto/RoomCryptoService.kt index f8c15fde47..124b2aef17 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/crypto/RoomCryptoService.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/crypto/RoomCryptoService.kt @@ -16,6 +16,8 @@ package im.vector.matrix.android.api.session.room.crypto +import im.vector.matrix.android.api.MatrixCallback + interface RoomCryptoService { fun isEncrypted(): Boolean @@ -23,4 +25,6 @@ interface RoomCryptoService { fun encryptionAlgorithm(): String? fun shouldEncryptForInvitedMembers(): Boolean + + fun enableEncryptionWithAlgorithm(algorithm: String, callback: MatrixCallback) } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/create/CreateRoomParams.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/create/CreateRoomParams.kt index bc1e941698..dbdd5b5a34 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/create/CreateRoomParams.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/create/CreateRoomParams.kt @@ -125,7 +125,7 @@ class CreateRoomParams { val contentMap = HashMap() contentMap["algorithm"] = algorithm - val algoEvent = Event(type = EventType.ENCRYPTION, + val algoEvent = Event(type = EventType.STATE_ROOM_ENCRYPTION, stateKey = "", content = contentMap.toContent() ) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/state/StateService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/state/StateService.kt index 06f4a9c7ee..3372eb874c 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/state/StateService.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/state/StateService.kt @@ -26,5 +26,10 @@ interface StateService { */ fun updateTopic(topic: String, callback: MatrixCallback) + /** + * Enable encryption of the room + */ + fun enableEncryption(algorithm: String, callback: MatrixCallback) + fun getStateEvent(eventType: String): Event? } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/DefaultCryptoService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/DefaultCryptoService.kt index be8918dac7..d0267e3345 100755 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/DefaultCryptoService.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/DefaultCryptoService.kt @@ -147,7 +147,7 @@ internal class DefaultCryptoService @Inject constructor( fun onStateEvent(roomId: String, event: Event) { when { - event.getClearType() == EventType.ENCRYPTION -> onRoomEncryptionEvent(roomId, event) + event.getClearType() == EventType.STATE_ROOM_ENCRYPTION -> onRoomEncryptionEvent(roomId, event) event.getClearType() == EventType.STATE_ROOM_MEMBER -> onRoomMembershipEvent(roomId, event) event.getClearType() == EventType.STATE_ROOM_HISTORY_VISIBILITY -> onRoomHistoryVisibilityEvent(roomId, event) } @@ -155,7 +155,7 @@ internal class DefaultCryptoService @Inject constructor( fun onLiveEvent(roomId: String, event: Event) { when { - event.getClearType() == EventType.ENCRYPTION -> onRoomEncryptionEvent(roomId, event) + event.getClearType() == EventType.STATE_ROOM_ENCRYPTION -> onRoomEncryptionEvent(roomId, event) event.getClearType() == EventType.STATE_ROOM_MEMBER -> onRoomMembershipEvent(roomId, event) event.getClearType() == EventType.STATE_ROOM_HISTORY_VISIBILITY -> onRoomHistoryVisibilityEvent(roomId, event) } @@ -482,7 +482,7 @@ internal class DefaultCryptoService @Inject constructor( */ override fun isRoomEncrypted(roomId: String): Boolean { val encryptionEvent = monarchy.fetchCopied { - EventEntity.where(it, roomId = roomId, type = EventType.ENCRYPTION).findFirst() + EventEntity.where(it, roomId = roomId, type = EventType.STATE_ROOM_ENCRYPTION).findFirst() } return encryptionEvent != null } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/DefaultRoom.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/DefaultRoom.kt index cca20fc5fc..5c87f84d73 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/DefaultRoom.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/DefaultRoom.kt @@ -19,14 +19,15 @@ package im.vector.matrix.android.internal.session.room import androidx.lifecycle.LiveData import androidx.lifecycle.Transformations import com.zhuinden.monarchy.Monarchy +import im.vector.matrix.android.api.MatrixCallback import im.vector.matrix.android.api.session.crypto.CryptoService import im.vector.matrix.android.api.session.room.Room import im.vector.matrix.android.api.session.room.members.MembershipService import im.vector.matrix.android.api.session.room.model.RoomSummary import im.vector.matrix.android.api.session.room.model.relation.RelationService import im.vector.matrix.android.api.session.room.notification.RoomPushRuleService -import im.vector.matrix.android.api.session.room.reporting.ReportingService import im.vector.matrix.android.api.session.room.read.ReadService +import im.vector.matrix.android.api.session.room.reporting.ReportingService import im.vector.matrix.android.api.session.room.send.DraftService import im.vector.matrix.android.api.session.room.send.SendService import im.vector.matrix.android.api.session.room.state.StateService @@ -91,4 +92,12 @@ internal class DefaultRoom @Inject constructor(override val roomId: String, override fun shouldEncryptForInvitedMembers(): Boolean { return cryptoService.shouldEncryptForInvitedMembers(roomId) } + + override fun enableEncryptionWithAlgorithm(algorithm: String, callback: MatrixCallback) { + if (isEncrypted()) { + callback.onFailure(IllegalStateException("Encryption is already enabled for this room")) + } else { + stateService.enableEncryption(algorithm, callback) + } + } } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/RoomSummaryUpdater.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/RoomSummaryUpdater.kt index 00703f85a5..9c73fe32f3 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/RoomSummaryUpdater.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/RoomSummaryUpdater.kt @@ -54,7 +54,7 @@ internal class RoomSummaryUpdater @Inject constructor( EventType.CALL_HANGUP, EventType.CALL_ANSWER, EventType.ENCRYPTED, - EventType.ENCRYPTION, + EventType.STATE_ROOM_ENCRYPTION, EventType.STATE_ROOM_THIRD_PARTY_INVITE, EventType.STICKER, EventType.STATE_ROOM_CREATE diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/state/DefaultStateService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/state/DefaultStateService.kt index 785fd9ae71..3cd73a97e0 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/state/DefaultStateService.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/state/DefaultStateService.kt @@ -22,6 +22,7 @@ import im.vector.matrix.android.api.MatrixCallback import im.vector.matrix.android.api.session.events.model.Event import im.vector.matrix.android.api.session.events.model.EventType import im.vector.matrix.android.api.session.room.state.StateService +import im.vector.matrix.android.internal.crypto.MXCRYPTO_ALGORITHM_MEGOLM import im.vector.matrix.android.internal.database.mapper.asDomain import im.vector.matrix.android.internal.database.model.EventEntity import im.vector.matrix.android.internal.database.query.prev @@ -31,6 +32,7 @@ import im.vector.matrix.android.internal.task.TaskExecutor import im.vector.matrix.android.internal.task.configureWith import io.realm.Realm import io.realm.RealmConfiguration +import java.security.InvalidParameterException internal class DefaultStateService @AssistedInject constructor(@Assisted private val roomId: String, @SessionDatabase @@ -52,10 +54,10 @@ internal class DefaultStateService @AssistedInject constructor(@Assisted private override fun updateTopic(topic: String, callback: MatrixCallback) { val params = SendStateTask.Params(roomId, - EventType.STATE_ROOM_TOPIC, - mapOf( - "topic" to topic - )) + EventType.STATE_ROOM_TOPIC, + mapOf( + "topic" to topic + )) sendStateTask .configureWith(params) { @@ -63,4 +65,22 @@ internal class DefaultStateService @AssistedInject constructor(@Assisted private } .executeBy(taskExecutor) } + + override fun enableEncryption(algorithm: String, callback: MatrixCallback) { + if (algorithm != MXCRYPTO_ALGORITHM_MEGOLM) { + callback.onFailure(InvalidParameterException("Only MXCRYPTO_ALGORITHM_MEGOLM algorithm is supported")) + } else { + val params = SendStateTask.Params(roomId, + EventType.STATE_ROOM_ENCRYPTION, + mapOf( + "algorithm" to algorithm + )) + + sendStateTask + .configureWith(params) { + this.callback = callback + } + .executeBy(taskExecutor) + } + } } diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/factory/EncryptionItemFactory.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/factory/EncryptionItemFactory.kt index 3f234fcd3e..fd29fe6bf5 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/factory/EncryptionItemFactory.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/factory/EncryptionItemFactory.kt @@ -65,7 +65,7 @@ class EncryptionItemFactory @Inject constructor(private val stringProvider: Stri private fun buildNoticeText(event: Event, senderName: String?): CharSequence? { return when { - EventType.ENCRYPTION == event.getClearType() -> { + EventType.STATE_ROOM_ENCRYPTION == event.getClearType() -> { val content = event.content.toModel() ?: return null stringProvider.getString(R.string.notice_end_to_end, senderName, content.algorithm) } diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/factory/TimelineItemFactory.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/factory/TimelineItemFactory.kt index 4a7a1e2a86..861be5cc86 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/factory/TimelineItemFactory.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/factory/TimelineItemFactory.kt @@ -54,7 +54,7 @@ class TimelineItemFactory @Inject constructor(private val messageItemFactory: Me EventType.CALL_ANSWER, EventType.REACTION, EventType.REDACTION, - EventType.ENCRYPTION -> noticeItemFactory.create(event, highlight, callback) + EventType.STATE_ROOM_ENCRYPTION -> noticeItemFactory.create(event, highlight, callback) // State room create EventType.STATE_ROOM_CREATE -> roomCreateItemFactory.create(event, callback) // Crypto diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/helper/TimelineDisplayableEvents.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/helper/TimelineDisplayableEvents.kt index b0f3e617a6..d669068cd7 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/helper/TimelineDisplayableEvents.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/helper/TimelineDisplayableEvents.kt @@ -34,7 +34,7 @@ object TimelineDisplayableEvents { EventType.CALL_HANGUP, EventType.CALL_ANSWER, EventType.ENCRYPTED, - EventType.ENCRYPTION, + EventType.STATE_ROOM_ENCRYPTION, EventType.STATE_ROOM_THIRD_PARTY_INVITE, EventType.STICKER, EventType.STATE_ROOM_CREATE,