Add allow to JoinRulesEventContent

Co-authored-by: Amanda Graven <amanda@amandag.net>
This commit is contained in:
Jonas Platte 2021-09-20 20:28:52 +02:00
parent ca49cf802d
commit 83b66ab8c2
No known key found for this signature in database
GPG Key ID: CC154DE0E30B7C67
2 changed files with 98 additions and 1 deletions

View File

@ -11,6 +11,7 @@ Breaking changes:
Improvements:
* Add `room::message::MessageType::body` accessor method
* Add (unstable) support for [MSC3083](https://github.com/matrix-org/matrix-doc/blob/main/proposals/3083-restricted-rooms.md)
# 0.24.5

View File

@ -1,8 +1,17 @@
//! Types for the *m.room.join_rules* event.
#[cfg(feature = "unstable-pre-spec")]
use std::collections::BTreeMap;
use ruma_events_macros::EventContent;
#[cfg(feature = "unstable-pre-spec")]
use ruma_identifiers::RoomId;
use ruma_serde::StringEnum;
#[cfg(feature = "unstable-pre-spec")]
use serde::de::{DeserializeOwned, Deserializer, Error};
use serde::{Deserialize, Serialize};
#[cfg(feature = "unstable-pre-spec")]
use serde_json::{value::RawValue as RawJsonValue, Value as JsonValue};
use crate::StateEvent;
@ -17,12 +26,29 @@ pub struct JoinRulesEventContent {
/// The type of rules used for users wishing to join this room.
#[ruma_event(skip_redaction)]
pub join_rule: JoinRule,
/// Allow rules used for the `restricted` join rule.
#[cfg(feature = "unstable-pre-spec")]
#[serde(default)]
#[ruma_event(skip_redaction)]
pub allow: Vec<AllowRule>,
}
impl JoinRulesEventContent {
/// Creates a new `JoinRulesEventContent` with the given rule.
pub fn new(join_rule: JoinRule) -> Self {
Self { join_rule }
Self {
join_rule,
#[cfg(feature = "unstable-pre-spec")]
allow: Vec::new(),
}
}
/// Creates a new `JoinRulesEventContent` with the restricted rule and the given set of allow
/// rules.
#[cfg(feature = "unstable-pre-spec")]
pub fn restricted(allow: Vec<AllowRule>) -> Self {
Self { join_rule: JoinRule::Restricted, allow }
}
}
@ -44,6 +70,11 @@ pub enum JoinRule {
/// Reserved but not yet implemented by the Matrix specification.
Private,
/// Users can join the room if they are invited, or if they meet any of the conditions
/// described in a set of [`AllowRule`]s.
#[cfg(feature = "unstable-pre-spec")]
Restricted,
/// Anyone can join the room without any prior action.
Public,
@ -57,3 +88,68 @@ impl JoinRule {
self.as_ref()
}
}
/// An allow rule which defines a condition that allows joining a room.
#[cfg(feature = "unstable-pre-spec")]
#[derive(Clone, Debug, PartialEq, Eq, Serialize)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
#[serde(tag = "type")]
pub enum AllowRule {
/// Joining is allowed if a user is already a member of the romm with the id `room_id`.
#[serde(rename = "m.room_membership")]
RoomMembership(RoomMembership),
#[doc(hidden)]
_Custom(CustomAllowRule),
}
/// Allow rule which grants permission to join based on the membership of another room.
#[cfg(feature = "unstable-pre-spec")]
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
pub struct RoomMembership {
/// The id of the room which being a member of grants permission to join another room.
pub room_id: RoomId,
}
#[cfg(feature = "unstable-pre-spec")]
#[doc(hidden)]
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
pub struct CustomAllowRule {
#[serde(rename = "type")]
rule_type: String,
#[serde(flatten)]
extra: BTreeMap<String, JsonValue>,
}
#[cfg(feature = "unstable-pre-spec")]
impl<'de> Deserialize<'de> for AllowRule {
fn deserialize<D>(deserializer: D) -> Result<AllowRule, D::Error>
where
D: Deserializer<'de>,
{
fn from_raw_json_value<T: DeserializeOwned, E: Error>(raw: &RawJsonValue) -> Result<T, E> {
serde_json::from_str(raw.get()).map_err(E::custom)
}
let json: Box<RawJsonValue> = Box::deserialize(deserializer)?;
// Extracts the `type` value.
#[derive(Deserialize)]
struct ExtractType {
rule_type: Option<String>,
}
// Get the value of `type` if present.
let rule_type = serde_json::from_str::<ExtractType>(json.get())
.map_err(serde::de::Error::custom)?
.rule_type;
match rule_type.as_deref() {
Some("m.room_membership") => from_raw_json_value(&json).map(Self::RoomMembership),
Some(_) => from_raw_json_value(&json).map(Self::_Custom),
None => Err(D::Error::missing_field("type")),
}
}
}