Compare commits

...

3 Commits

Author SHA1 Message Date
Ginger
77e9c5df43 fix: Fix registration_terms default in example config 2026-04-06 14:56:48 -04:00
Ginger
70b0976bb5 chore: News fragment 2026-04-06 13:35:40 -04:00
Ginger
06a86ed94a feat: Add support for terms and conditions when registering 2026-04-06 12:51:15 -04:00
5 changed files with 62 additions and 2 deletions

View File

@@ -0,0 +1 @@
Added support for requiring users to accept terms and conditions when registering.

View File

@@ -523,6 +523,18 @@
#
#recaptcha_private_site_key =
# Policy documents, such as terms and conditions or a privacy policy,
# which users must agree to when registering an account.
#
# Example:
# ```
# [global.registration_terms.privacy_policy]
# en = { name = "Privacy Policy", url = "https://homeserver.example/en/privacy_policy.html" }
# es = { name = "Política de Privacidad", url = "https://homeserver.example/es/privacy_policy.html" }
# ```
#
#registration_terms = false
# Controls whether encrypted rooms and events are allowed.
#
#allow_encryption = true

View File

@@ -462,6 +462,31 @@ async fn create_registration_uiaa_session(
flows.push(untrusted_flow);
}
// Require all users to agree to the terms and conditions, if configured
let terms = &services.config.registration_terms;
if !terms.is_empty() {
let mut terms =
serde_json::to_value(terms.clone()).expect("failed to serialize terms");
// Insert a dummy `version` field
for (_, documents) in terms.as_object_mut().unwrap() {
let documents = documents.as_object_mut().unwrap();
documents.insert("version".to_owned(), "latest".into());
}
params.insert(
AuthType::Terms.as_str().to_owned(),
serde_json::json!({
"policies": terms,
}),
);
for flow in &mut flows {
flow.stages.insert(0, AuthType::Terms);
}
}
if flows.is_empty() {
// No flows are configured. Bail out by default
// unless open registration was explicitly enabled.

View File

@@ -4,7 +4,7 @@
pub mod proxy;
use std::{
collections::{BTreeMap, BTreeSet},
collections::{BTreeMap, BTreeSet, HashMap},
net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr},
path::PathBuf,
};
@@ -22,7 +22,7 @@
OwnedRoomId, OwnedRoomOrAliasId, OwnedServerName, OwnedUserId, RoomVersionId,
api::client::discovery::{discover_homeserver::RtcFocusInfo, discover_support::ContactRole},
};
use serde::{Deserialize, de::IgnoredAny};
use serde::{Deserialize, Serialize, de::IgnoredAny};
use url::Url;
use self::proxy::ProxyConfig;
@@ -655,6 +655,20 @@ pub struct Config {
/// even if `recaptcha_site_key` is set.
pub recaptcha_private_site_key: Option<String>,
/// Policy documents, such as terms and conditions or a privacy policy,
/// which users must agree to when registering an account.
///
/// Example:
/// ```
/// [global.registration_terms.privacy_policy]
/// en = { name = "Privacy Policy", url = "https://homeserver.example/en/privacy_policy.html" }
/// es = { name = "Política de Privacidad", url = "https://homeserver.example/es/privacy_policy.html" }
/// ```
///
/// default: {}
#[serde(default)]
pub registration_terms: HashMap<String, HashMap<String, TermsDocument>>,
/// Controls whether encrypted rooms and events are allowed.
#[serde(default = "true_fn")]
pub allow_encryption: bool,
@@ -2494,6 +2508,13 @@ pub struct SmtpConfig {
pub require_email_for_token_registration: bool,
}
/// A policy document for use with a m.login.terms stage.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct TermsDocument {
pub name: String,
pub url: String,
}
const DEPRECATED_KEYS: &[&str] = &[
"cache_capacity",
"conduit_cache_capacity_modifier",

View File

@@ -455,6 +455,7 @@ async fn check_stage(
})
}
},
| AuthData::Terms(_) => Ok(AuthType::Terms),
| _ => Err(StandardErrorBody {
kind: ErrorKind::Unrecognized,
message: "Unsupported stage type".into(),