From a14556da97cd70a2c6bc2e868b248bca5e0ba828 Mon Sep 17 00:00:00 2001 From: Jason Volk Date: Sat, 1 Nov 2025 22:44:36 +0000 Subject: [PATCH] Implement `encryption_enabled_by_default_for_room_type`. (closes #29) Signed-off-by: Jason Volk --- src/api/client/room/create.rs | 36 ++++++++++++++++++++++++++++++++++- src/core/config/mod.rs | 11 +++++++++++ tuwunel-example.toml | 11 +++++++++++ 3 files changed, 57 insertions(+), 1 deletion(-) diff --git a/src/api/client/room/create.rs b/src/api/client/room/create.rs index ae645320..3cbdac3b 100644 --- a/src/api/client/room/create.rs +++ b/src/api/client/room/create.rs @@ -3,7 +3,8 @@ use std::collections::BTreeMap; use axum::extract::State; use futures::{FutureExt, future::OptionFuture}; use ruma::{ - CanonicalJsonObject, Int, OwnedRoomAliasId, OwnedRoomId, OwnedUserId, RoomId, RoomVersionId, + CanonicalJsonObject, EventEncryptionAlgorithm, Int, OwnedRoomAliasId, OwnedRoomId, + OwnedUserId, RoomId, RoomVersionId, api::client::room::{ self, create_room, create_room::v3::{CreationContent, RoomPreset}, @@ -13,6 +14,7 @@ use ruma::{ room::{ canonical_alias::RoomCanonicalAliasEventContent, create::RoomCreateEventContent, + encryption::RoomEncryptionEventContent, guest_access::{GuestAccess, RoomGuestAccessEventContent}, history_visibility::{HistoryVisibility, RoomHistoryVisibilityEventContent}, join_rules::{JoinRule, RoomJoinRulesEventContent}, @@ -262,6 +264,7 @@ pub(crate) async fn create_room_route( .await?; // 6. Events listed in initial_state + let mut is_encrypted = false; for event in &body.initial_state { let mut pdu_builder = event .deserialize_as_unchecked::() @@ -292,6 +295,10 @@ pub(crate) async fn create_room_route( continue; } + if pdu_builder.event_type == TimelineEventType::RoomEncryption { + is_encrypted = true; + } + services .timeline .build_and_append_pdu(pdu_builder, sender_user, &room_id, &state_lock) @@ -299,6 +306,33 @@ pub(crate) async fn create_room_route( .await?; } + if services.config.allow_encryption && !is_encrypted { + use RoomPreset::*; + + let config = services + .config + .encryption_enabled_by_default_for_room_type + .as_deref() + .unwrap_or("off"); + + let invite = matches!(config, "invite"); + let always = matches!(config, "all" | "invite"); + if always || (invite && matches!(preset, PrivateChat | TrustedPrivateChat)) { + let algorithm = EventEncryptionAlgorithm::MegolmV1AesSha2; + let content = RoomEncryptionEventContent::new(algorithm); + services + .timeline + .build_and_append_pdu( + PduBuilder::state(String::new(), &content), + sender_user, + &room_id, + &state_lock, + ) + .boxed() + .await?; + } + } + // 7. Events implied by name and topic if let Some(name) = &body.name { services diff --git a/src/core/config/mod.rs b/src/core/config/mod.rs index 5337b448..85a06213 100644 --- a/src/core/config/mod.rs +++ b/src/core/config/mod.rs @@ -590,6 +590,17 @@ pub struct Config { #[serde(default = "true_fn")] pub allow_encryption: bool, + /// Controls whether locally-created rooms should be end-to-end encrypted by + /// default. This option is equivalent to the one found in Synapse. + /// + /// Options: + /// - "all": All created rooms are encrypted. + /// - "invite": Any room created with `private_chat` or + /// `trusted_private_chat` presets. + /// - Other values default to no effect. + #[serde(default)] + pub encryption_enabled_by_default_for_room_type: Option, + /// Controls whether federation is allowed or not. It is not recommended to /// disable this after installation due to potential federation breakage but /// this is technically not a permanent setting. diff --git a/tuwunel-example.toml b/tuwunel-example.toml index 31aa653f..ead806d9 100644 --- a/tuwunel-example.toml +++ b/tuwunel-example.toml @@ -459,6 +459,17 @@ # #allow_encryption = true +# Controls whether locally-created rooms should be end-to-end encrypted by +# default. This option is equivalent to the one found in Synapse. +# +# Options: +# - "all": All created rooms are encrypted. +# - "invite": Any room created with `private_chat` or +# `trusted_private_chat` presets. +# - Other values default to no effect. +# +#encryption_enabled_by_default_for_room_type = false + # Controls whether federation is allowed or not. It is not recommended to # disable this after installation due to potential federation breakage but # this is technically not a permanent setting.