Merge remote-tracking branch 'upstream/main' into conduwuit-changes

This commit is contained in:
strawberry 2024-03-02 10:51:18 -05:00
commit 1623fffe15
10 changed files with 140 additions and 13 deletions

View File

@ -24,6 +24,8 @@ Improvements:
- Add deprecated `address` and `medium` 3PID fields for `m.login.password`
login type.
- Add optional cookie field to `session::sso_login*::v3` responses.
- Add support for local user erasure to `account::deactivate::v3::Request`,
according to MSC4025.
# 0.17.4

View File

@ -39,6 +39,13 @@ pub mod v3 {
/// identifier.
#[serde(skip_serializing_if = "Option::is_none")]
pub id_server: Option<String>,
/// Whether the user would like their content to be erased as much as possible from the
/// server.
///
/// Defaults to `false`.
#[serde(default, skip_serializing_if = "ruma_common::serde::is_default")]
pub erase: bool,
}
/// Response type for the `deactivate` endpoint.

View File

@ -1,5 +1,10 @@
# [unreleased]
Bug fixes:
- The `MembershipState::Invite` to `MembershipState::Knock` membership change
now returns `MembershipChange::Error`, due to a spec clarification
Breaking changes:
- The properties of `SecretStorageV1AesHmacSha2Properties` are now `Option`al.
@ -22,6 +27,7 @@ Improvements:
- Add unstable support for manually marking rooms as unread through [MSC2867](https://github.com/matrix-org/matrix-spec-proposals/pull/2867)
and the room account data `m.marked_unread` event (unstable type `com.famedly.marked_unread`)
- Implement `From<JoinRule>` for `SpaceRoomJoinRule`
- Add `filename` and `formatted` fields to media event contents to support media captions as per [MSC2530](https://github.com/matrix-org/matrix-spec-proposals/pull/2530)
# 0.27.11

View File

@ -126,6 +126,7 @@ pub(super) fn membership_change<'a>(
| (St::Ban, St::Invite)
| (St::Ban, St::Join)
| (St::Join, St::Knock)
| (St::Invite, St::Knock)
| (St::Ban, St::Knock)
| (St::Knock, St::Join) => Ch::Error,
(St::Join, St::Join)
@ -143,7 +144,7 @@ pub(super) fn membership_change<'a>(
(St::Join, St::Ban) => Ch::KickedAndBanned,
(St::Leave, St::Invite) => Ch::Invited,
(St::Ban, St::Leave) => Ch::Unbanned,
(St::Leave, St::Knock) | (St::Invite, St::Knock) => Ch::Knocked,
(St::Leave, St::Knock) => Ch::Knocked,
(St::Knock, St::Invite) => Ch::KnockAccepted,
(St::Knock, St::Leave) if sender == state_key => Ch::KnockRetracted,
(St::Knock, St::Leave) => Ch::KnockDenied,

View File

@ -4,6 +4,7 @@ use js_int::UInt;
use ruma_common::OwnedMxcUri;
use serde::{Deserialize, Serialize};
use super::FormattedBody;
use crate::room::{EncryptedFile, MediaSource};
/// The payload for an audio message.
@ -12,8 +13,19 @@ use crate::room::{EncryptedFile, MediaSource};
#[serde(tag = "msgtype", rename = "m.audio")]
pub struct AudioMessageEventContent {
/// The textual representation of this message.
///
/// If the `filename` field is not set or has the same value, this is the filename of the
/// uploaded file. Otherwise, this should be interpreted as a user-written media caption.
pub body: String,
/// Formatted form of the message `body`, if `body` is a caption.
#[serde(flatten)]
pub formatted: Option<FormattedBody>,
/// The original filename of the uploaded file.
#[serde(skip_serializing_if = "Option::is_none")]
pub filename: Option<String>,
/// The source of the audio clip.
#[serde(flatten)]
pub source: MediaSource,
@ -44,6 +56,8 @@ impl AudioMessageEventContent {
pub fn new(body: String, source: MediaSource) -> Self {
Self {
body,
formatted: None,
filename: None,
source,
info: None,
#[cfg(feature = "unstable-msc3245-v1-compat")]
@ -64,6 +78,24 @@ impl AudioMessageEventContent {
Self::new(body, MediaSource::Encrypted(Box::new(file)))
}
/// Creates a new `AudioMessageEventContent` from `self` with the `filename` field set to the
/// given value.
///
/// Since the field is public, you can also assign to it directly. This method merely acts
/// as a shorthand for that, because it is very common to set this field.
pub fn filename(self, filename: impl Into<Option<String>>) -> Self {
Self { filename: filename.into(), ..self }
}
/// Creates a new `AudioMessageEventContent` from `self` with the `formatted` field set to the
/// given value.
///
/// Since the field is public, you can also assign to it directly. This method merely acts
/// as a shorthand for that, because it is very common to set this field.
pub fn formatted(self, formatted: impl Into<Option<FormattedBody>>) -> Self {
Self { formatted: formatted.into(), ..self }
}
/// Creates a new `AudioMessageEventContent` from `self` with the `info` field set to the given
/// value.
///

View File

@ -2,6 +2,7 @@ use js_int::UInt;
use ruma_common::OwnedMxcUri;
use serde::{Deserialize, Serialize};
use super::FormattedBody;
use crate::room::{EncryptedFile, MediaSource, ThumbnailInfo};
/// The payload for a file message.
@ -11,9 +12,14 @@ use crate::room::{EncryptedFile, MediaSource, ThumbnailInfo};
pub struct FileMessageEventContent {
/// A human-readable description of the file.
///
/// This is recommended to be the filename of the original upload.
/// If the `filename` field is not set or has the same value, this is the filename of the
/// uploaded file. Otherwise, this should be interpreted as a user-written media caption.
pub body: String,
/// Formatted form of the message `body`, if `body` is a caption.
#[serde(flatten)]
pub formatted: Option<FormattedBody>,
/// The original filename of the uploaded file.
#[serde(skip_serializing_if = "Option::is_none")]
pub filename: Option<String>,
@ -30,7 +36,7 @@ pub struct FileMessageEventContent {
impl FileMessageEventContent {
/// Creates a new `FileMessageEventContent` with the given body and source.
pub fn new(body: String, source: MediaSource) -> Self {
Self { body, filename: None, source, info: None }
Self { body, formatted: None, filename: None, source, info: None }
}
/// Creates a new non-encrypted `FileMessageEventContent` with the given body and url.
@ -53,6 +59,15 @@ impl FileMessageEventContent {
Self { filename: filename.into(), ..self }
}
/// Creates a new `FileMessageEventContent` from `self` with the `formatted` field set to the
/// given value.
///
/// Since the field is public, you can also assign to it directly. This method merely acts
/// as a shorthand for that, because it is very common to set this field.
pub fn formatted(self, formatted: impl Into<Option<FormattedBody>>) -> Self {
Self { formatted: formatted.into(), ..self }
}
/// Creates a new `FileMessageEventContent` from `self` with the `info` field set to the given
/// value.
///

View File

@ -1,6 +1,7 @@
use ruma_common::OwnedMxcUri;
use serde::{Deserialize, Serialize};
use super::FormattedBody;
use crate::room::{EncryptedFile, ImageInfo, MediaSource};
/// The payload for an image message.
@ -10,10 +11,18 @@ use crate::room::{EncryptedFile, ImageInfo, MediaSource};
pub struct ImageMessageEventContent {
/// A textual representation of the image.
///
/// Could be the alt text of the image, the filename of the image, or some kind of content
/// description for accessibility e.g. "image attachment".
/// If the `filename` field is not set or has the same value, this is the filename of the
/// uploaded file. Otherwise, this should be interpreted as a user-written media caption.
pub body: String,
/// Formatted form of the message `body`, if `body` is a caption.
#[serde(flatten)]
pub formatted: Option<FormattedBody>,
/// The original filename of the uploaded file.
#[serde(skip_serializing_if = "Option::is_none")]
pub filename: Option<String>,
/// The source of the image.
#[serde(flatten)]
pub source: MediaSource,
@ -26,7 +35,7 @@ pub struct ImageMessageEventContent {
impl ImageMessageEventContent {
/// Creates a new `ImageMessageEventContent` with the given body and source.
pub fn new(body: String, source: MediaSource) -> Self {
Self { body, source, info: None }
Self { body, formatted: None, filename: None, source, info: None }
}
/// Creates a new non-encrypted `ImageMessageEventContent` with the given body and url.
@ -40,6 +49,24 @@ impl ImageMessageEventContent {
Self::new(body, MediaSource::Encrypted(Box::new(file)))
}
/// Creates a new `ImageMessageEventContent` from `self` with the `filename` field set to the
/// given value.
///
/// Since the field is public, you can also assign to it directly. This method merely acts
/// as a shorthand for that, because it is very common to set this field.
pub fn filename(self, filename: impl Into<Option<String>>) -> Self {
Self { filename: filename.into(), ..self }
}
/// Creates a new `ImageMessageEventContent` from `self` with the `formatted` field set to the
/// given value.
///
/// Since the field is public, you can also assign to it directly. This method merely acts
/// as a shorthand for that, because it is very common to set this field.
pub fn formatted(self, formatted: impl Into<Option<FormattedBody>>) -> Self {
Self { formatted: formatted.into(), ..self }
}
/// Creates a new `ImageMessageEventContent` from `self` with the `info` field set to the given
/// value.
///

View File

@ -4,6 +4,7 @@ use js_int::UInt;
use ruma_common::OwnedMxcUri;
use serde::{Deserialize, Serialize};
use super::FormattedBody;
use crate::room::{EncryptedFile, MediaSource, ThumbnailInfo};
/// The payload for a video message.
@ -11,10 +12,20 @@ use crate::room::{EncryptedFile, MediaSource, ThumbnailInfo};
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
#[serde(tag = "msgtype", rename = "m.video")]
pub struct VideoMessageEventContent {
/// A description of the video, e.g. "Gangnam Style", or some kind of content description for
/// accessibility, e.g. "video attachment".
/// A description of the video.
///
/// If the `filename` field is not set or has the same value, this is the filename of the
/// uploaded file. Otherwise, this should be interpreted as a user-written media caption.
pub body: String,
/// Formatted form of the message `body`, if `body` is a caption.
#[serde(flatten)]
pub formatted: Option<FormattedBody>,
/// The original filename of the uploaded file.
#[serde(skip_serializing_if = "Option::is_none")]
pub filename: Option<String>,
/// The source of the video clip.
#[serde(flatten)]
pub source: MediaSource,
@ -27,7 +38,7 @@ pub struct VideoMessageEventContent {
impl VideoMessageEventContent {
/// Creates a new `VideoMessageEventContent` with the given body and source.
pub fn new(body: String, source: MediaSource) -> Self {
Self { body, source, info: None }
Self { body, formatted: None, filename: None, source, info: None }
}
/// Creates a new non-encrypted `VideoMessageEventContent` with the given body and url.
@ -41,6 +52,24 @@ impl VideoMessageEventContent {
Self::new(body, MediaSource::Encrypted(Box::new(file)))
}
/// Creates a new `VideoMessageEventContent` from `self` with the `filename` field set to the
/// given value.
///
/// Since the field is public, you can also assign to it directly. This method merely acts
/// as a shorthand for that, because it is very common to set this field.
pub fn filename(self, filename: impl Into<Option<String>>) -> Self {
Self { filename: filename.into(), ..self }
}
/// Creates a new `VideoMessageEventContent` from `self` with the `formatted` field set to the
/// given value.
///
/// Since the field is public, you can also assign to it directly. This method merely acts
/// as a shorthand for that, because it is very common to set this field.
pub fn formatted(self, formatted: impl Into<Option<FormattedBody>>) -> Self {
Self { formatted: formatted.into(), ..self }
}
/// Creates a new `VideoMessageEventContent` from `self` with the `info` field set to the given
/// value.
///

View File

@ -1,5 +1,11 @@
# [unreleased]
Bug fixes:
* Disallow `invite` -> `knock` membership transition
* The spec was determined to be right about rejecting it in the first place:
<https://github.com/matrix-org/matrix-spec/pull/1717>
# 0.10.0
Improvements:

View File

@ -702,7 +702,7 @@ fn valid_membership_change(
false
} else {
// 2. If `sender` does not match `state_key`, reject.
// 3. If the `sender`'s current membership is not `ban` or `join`, allow.
// 3. If the `sender`'s current membership is not `ban`, `invite`, or `join`, allow.
// 4. Otherwise, reject.
if sender != target_user {
warn!(
@ -711,11 +711,13 @@ fn valid_membership_change(
"Can't make another user join, sender did not match target"
);
false
} else if matches!(sender_membership, MembershipState::Ban | MembershipState::Join)
{
} else if matches!(
sender_membership,
MembershipState::Ban | MembershipState::Invite | MembershipState::Join
) {
warn!(
?target_user_membership_event_id,
"Membership state of ban or join are invalid",
"Membership state of ban, invite or join are invalid",
);
false
} else {