mirror of
https://github.com/element-hq/synapse.git
synced 2026-07-28 14:19:59 +00:00
Merge remote-tracking branch 'origin/develop' into anoa/msc4429
This commit is contained in:
@@ -9,7 +9,9 @@ on:
|
||||
env:
|
||||
# We use nightly so that `fmt` correctly groups together imports, and
|
||||
# clippy correctly fixes up the benchmarks.
|
||||
RUST_VERSION: nightly-2025-06-24
|
||||
#
|
||||
# Note: This should match the nightly rust version in `tests.yml`.
|
||||
RUST_VERSION: nightly-2025-03-27
|
||||
|
||||
jobs:
|
||||
fixup:
|
||||
|
||||
@@ -13,6 +13,16 @@ concurrency:
|
||||
|
||||
env:
|
||||
RUST_VERSION: 1.87.0
|
||||
# This nightly is roughly the last to be branded 1.87.0.
|
||||
#
|
||||
# We know this, as 1.87.0 was branched from master on 2025-03-28. Shortly
|
||||
# afterwards, nightlies were then branded as 1.88.0. See
|
||||
# https://releases.rs/docs/1.87.0/ for where we get the dates.
|
||||
#
|
||||
# Technically the last 1.87.0 nightly was 2025-03-29, but that all depends on
|
||||
# at which time of day they cut the release and when the nightly is built.
|
||||
# It's safer for future releases to just do the day before.
|
||||
RUST_NIGHTLY_VERSION: nightly-2025-03-27 # last nightly before 1.88.0
|
||||
|
||||
jobs:
|
||||
# Job to detect what has changed so we don't run e.g. Rust checks on PRs that
|
||||
@@ -240,7 +250,7 @@ jobs:
|
||||
- name: Install Rust
|
||||
uses: dtolnay/rust-toolchain@e97e2d8cc328f1b50210efc529dca0028893a2d9 # master
|
||||
with:
|
||||
toolchain: nightly-2026-02-01
|
||||
toolchain: ${{ env.RUST_NIGHTLY_VERSION }}
|
||||
components: clippy
|
||||
- uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1
|
||||
|
||||
@@ -296,7 +306,7 @@ jobs:
|
||||
with:
|
||||
# We use nightly so that we can use some unstable options that we use in
|
||||
# `.rustfmt.toml`.
|
||||
toolchain: nightly-2025-04-23
|
||||
toolchain: ${{ env.RUST_NIGHTLY_VERSION }}
|
||||
components: rustfmt
|
||||
- uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1
|
||||
|
||||
@@ -677,7 +687,12 @@ jobs:
|
||||
- changes
|
||||
|
||||
cargo-test:
|
||||
if: ${{ needs.changes.outputs.rust == 'true' }}
|
||||
# We need to explicitly specify `!cancelled() && !failure()` as otherwise
|
||||
# GitHub will implicitly add `success()`, which will be `false` when any job
|
||||
# in `needs`, or its dependents, is skipped. Most notably, jobs like
|
||||
# `lint-readme`, a dependency of `linting-done`, are unlikely to run very
|
||||
# often - and would result in this job being skipped.
|
||||
if: ${{ !cancelled() && !failure() && needs.changes.outputs.rust == 'true' }}
|
||||
runs-on: ubuntu-latest
|
||||
needs:
|
||||
- linting-done
|
||||
@@ -697,7 +712,8 @@ jobs:
|
||||
# We want to ensure that the cargo benchmarks still compile, which requires a
|
||||
# nightly compiler.
|
||||
cargo-bench:
|
||||
if: ${{ needs.changes.outputs.rust == 'true' }}
|
||||
# See `cargo-test` above for why we need to specify `!cancelled() && !failure()`.
|
||||
if: ${{ !cancelled() && !failure() && needs.changes.outputs.rust == 'true' }}
|
||||
runs-on: ubuntu-latest
|
||||
needs:
|
||||
- linting-done
|
||||
@@ -709,7 +725,7 @@ jobs:
|
||||
- name: Install Rust
|
||||
uses: dtolnay/rust-toolchain@e97e2d8cc328f1b50210efc529dca0028893a2d9 # master
|
||||
with:
|
||||
toolchain: nightly-2022-12-01
|
||||
toolchain: ${{ env.RUST_NIGHTLY_VERSION }}
|
||||
- uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1
|
||||
|
||||
- run: cargo bench --no-run
|
||||
|
||||
+47
@@ -1,3 +1,50 @@
|
||||
# Synapse 1.156.0rc1 (2026-06-30)
|
||||
|
||||
## Features
|
||||
|
||||
- Expose [MSC4354 Sticky Events](https://github.com/matrix-org/matrix-spec-proposals/pull/4354) over [MSC4186 (Simplified) Sliding Sync](https://github.com/matrix-org/matrix-spec-proposals/pull/4186). ([\#19591](https://github.com/element-hq/synapse/issues/19591))
|
||||
- Stabilize support for sending ephemeral events to application services, as per [MSC2409](https://github.com/matrix-org/matrix-spec-proposals/pull/2409). Contributed by @jason-famedly @ Famedly. ([\#19758](https://github.com/element-hq/synapse/issues/19758))
|
||||
- Include `allowed_room_ids` in the `/summary` client-server API response for rooms with restricted join rules, as required by Matrix 1.15.
|
||||
Contributed by @FrenchGithubUser @Famedly. ([\#19762](https://github.com/element-hq/synapse/issues/19762))
|
||||
- [MSC4140: Cancellable delayed events](https://github.com/matrix-org/matrix-spec-proposals/pull/4140): Allow authentication on delayed event management endpoints (such as `/restart`) to bypass ratelimits for unauthenticated requests based on the client IP address. ([\#19794](https://github.com/element-hq/synapse/issues/19794))
|
||||
- Add new metric `synapse_non_deactivated_user_count` which tracks the number of non-deactivated users in the database, split by `app_service`. ([\#19848](https://github.com/element-hq/synapse/issues/19848))
|
||||
- The `GET /_matrix/client/unstable/org.matrix.msc1763/retention/configuration` endpoint is now provided when retention
|
||||
is enabled and `experimental_features.msc1763_enabled` is enabled, based on
|
||||
[MSC1763](https://github.com/matrix-org/matrix-spec-proposals/pull/1763). ([\#19853](https://github.com/element-hq/synapse/issues/19853))
|
||||
- Add experimental support for [MSC4491: Invite reasons in room creation](https://github.com/matrix-org/matrix-spec-proposals/pull/4491). ([\#19874](https://github.com/element-hq/synapse/issues/19874))
|
||||
|
||||
## Bugfixes
|
||||
|
||||
- Provide remote servers a way to find out about an event created during the remote join handshake. Contributed by @FrenchGithubUser and @jason-famedly @ Famedly. ([\#19390](https://github.com/element-hq/synapse/issues/19390), [\#19855](https://github.com/element-hq/synapse/issues/19855), [\#19856](https://github.com/element-hq/synapse/issues/19856))
|
||||
- Advertise `org.matrix.msc4143` in `unstable_features` when `msc4143_enabled` is set. ([\#19646](https://github.com/element-hq/synapse/issues/19646))
|
||||
- Fix a long-standing bug where the badge notification count for a room could become permanently inflated if a read receipt was sent before the room's notification counts were first summarised. ([\#19785](https://github.com/element-hq/synapse/issues/19785))
|
||||
- Fix startup listener logging to report the actual bound TCP port, so listeners configured with port `0` no longer log `Synapse now listening on TCP port 0`. ([\#19810](https://github.com/element-hq/synapse/issues/19810))
|
||||
- Fix notification counts being inflated after a `/purge_history` when notifications had already been rotated into the summary table. ([\#19834](https://github.com/element-hq/synapse/issues/19834))
|
||||
- Fix `/sync` caching transient errors for the `sync_response_cache_duration`. ([\#19845](https://github.com/element-hq/synapse/issues/19845))
|
||||
- Fix local events being deleted by the [Purge History admin API](https://element-hq.github.io/synapse/v1.155/admin_api/purge_history_api.html) despite `delete_local_events` being set to false, in room versions other than 1 and 2. ([\#19850](https://github.com/element-hq/synapse/issues/19850))
|
||||
- Fix a bug where a user's dehydrated device ([MSC3814](https://github.com/matrix-org/matrix-spec-proposals/pull/3814)) was deleted when their device list was synced from Matrix Authentication Service (e.g. upon logging out their last device), breaking offline key delivery. ([\#19892](https://github.com/element-hq/synapse/issues/19892))
|
||||
|
||||
## Improved Documentation
|
||||
|
||||
- Update `auto_join_rooms` config documentation to cover requirements for auto-joining invite-only rooms. ([\#19660](https://github.com/element-hq/synapse/issues/19660))
|
||||
- Add stable endpoint for [MSC3266: Room summary API](https://github.com/matrix-org/matrix-spec-proposals/pull/3266) into worker docs. Contributed by @olmari. ([\#19788](https://github.com/element-hq/synapse/issues/19788))
|
||||
- Tweak wording of Rust crate dependency update policy. ([\#19829](https://github.com/element-hq/synapse/issues/19829))
|
||||
- Fixed the Admin API user endpoint documentation examples to use JSON booleans (true/false) instead of numeric (0/1) values. ([\#19847](https://github.com/element-hq/synapse/issues/19847))
|
||||
|
||||
## Internal Changes
|
||||
|
||||
- Make `simple_select_one_onecol_txn()` more helpful by naming the table of the select - as all other query wrapper functions already did. ([\#19869](https://github.com/element-hq/synapse/issues/19869))
|
||||
- Refactor `get_user_which_could_invite` logic to reuse `get_users_which_can_issue_invite`. Contributed by Noah Markert. ([\#19732](https://github.com/element-hq/synapse/issues/19732))
|
||||
- Fix a flaky test (`twisted.protocols.amp.TooLong` error under `trial -jN`) caused by an oversized debug log line. ([\#19832](https://github.com/element-hq/synapse/issues/19832))
|
||||
- Upload Complement test logs as CI artifacts instead of printing the raw output to the build log. ([\#19840](https://github.com/element-hq/synapse/issues/19840))
|
||||
- Fix release script considering any workflow completion as successful. ([\#19843](https://github.com/element-hq/synapse/issues/19843))
|
||||
- Force keyword-args for clear `default_config(server_name="test")` usage in test utilities. ([\#19849](https://github.com/element-hq/synapse/issues/19849))
|
||||
- Add `.ruff_cache/` directory to `.gitignore`. ([\#19854](https://github.com/element-hq/synapse/issues/19854))
|
||||
- Bump `poetry` in CI from `2.2.1` to `2.4.1`. ([\#19866](https://github.com/element-hq/synapse/issues/19866), [\#19877](https://github.com/element-hq/synapse/issues/19877))
|
||||
- Split out `deferred` and `tokio_runtime` to their own Rust modules. ([\#19868](https://github.com/element-hq/synapse/issues/19868))
|
||||
- Prevent the `cargo-test` and `cargo-bench` CI jobs from being skipped, even on PRs that have Rust changes. ([\#19883](https://github.com/element-hq/synapse/issues/19883))
|
||||
|
||||
|
||||
# Synapse 1.155.0 (2026-06-16)
|
||||
|
||||
## End of Life of Debian 12 Bookworm
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
Provide remote servers a way to find out about an event created during the remote join handshake. Contributed by @FrenchGithubUser and @jason-famedly @ Famedly.
|
||||
@@ -1 +0,0 @@
|
||||
Expose [MSC4354 Sticky Events](https://github.com/matrix-org/matrix-spec-proposals/pull/4354) over [MSC4186 (Simplified) Sliding Sync](https://github.com/matrix-org/matrix-spec-proposals/pull/4186).
|
||||
@@ -1 +0,0 @@
|
||||
Advertise `org.matrix.msc4143` in `unstable_features` when `msc4143_enabled` is set.
|
||||
@@ -1 +0,0 @@
|
||||
Update `auto_join_rooms` config documentation to cover requirements for auto-joining invite-only rooms.
|
||||
@@ -1 +0,0 @@
|
||||
Refactor `get_user_which_could_invite` logic to reuse `get_users_which_can_issue_invite`. Contributed by Noah Markert.
|
||||
@@ -1 +0,0 @@
|
||||
Stabilize support for sending ephemeral events to application services, as per [MSC2409](https://github.com/matrix-org/matrix-spec-proposals/pull/2409). Contributed by @jason-famedly @ Famedly.
|
||||
@@ -1,2 +0,0 @@
|
||||
Include `allowed_room_ids` in the `/summary` client-server API response for rooms with restricted join rules, as required by Matrix 1.15.
|
||||
Contributed by @FrenchGithubUser @Famedly.
|
||||
@@ -1 +0,0 @@
|
||||
Fix a long-standing bug where the badge notification count for a room could become permanently inflated if a read receipt was sent before the room's notification counts were first summarised.
|
||||
@@ -1 +0,0 @@
|
||||
Add stable endpoint for [MSC3266: Room summary API](https://github.com/matrix-org/matrix-spec-proposals/pull/3266) into worker docs. Contributed by @olmari.
|
||||
@@ -1 +0,0 @@
|
||||
[MSC4140: Cancellable delayed events](https://github.com/matrix-org/matrix-spec-proposals/pull/4140): Allow authentication on delayed event management endpoints (such as `/restart`) to bypass ratelimits for unauthenticated requests based on the client IP address.
|
||||
@@ -1 +0,0 @@
|
||||
Fix startup listener logging to report the actual bound TCP port, so listeners configured with port `0` no longer log `Synapse now listening on TCP port 0`.
|
||||
@@ -1 +0,0 @@
|
||||
Tweak wording of Rust crate dependency update policy.
|
||||
@@ -1 +0,0 @@
|
||||
Fix a flaky test (`twisted.protocols.amp.TooLong` error under `trial -jN`) caused by an oversized debug log line.
|
||||
@@ -1 +0,0 @@
|
||||
Fix notification counts being inflated after a `/purge_history` when notifications had already been rotated into the summary table.
|
||||
@@ -1 +0,0 @@
|
||||
Upload Complement test logs as CI artifacts instead of printing the raw output to the build log.
|
||||
@@ -1 +0,0 @@
|
||||
Fix release script considering any workflow completion as successful.
|
||||
@@ -1 +0,0 @@
|
||||
Fix `/sync` caching transient errors for the `sync_response_cache_duration`.
|
||||
@@ -1 +0,0 @@
|
||||
Fixed the Admin API user endpoint documentation examples to use JSON booleans (true/false) instead of numeric (0/1) values.
|
||||
@@ -1 +0,0 @@
|
||||
Add new metric `synapse_non_deactivated_user_count` which tracks the number of non-deactivated users in the database, split by `app_service`.
|
||||
@@ -1 +0,0 @@
|
||||
Force keyword-args for clear `default_config(server_name="test")` usage in test utilities.
|
||||
@@ -1 +0,0 @@
|
||||
Fix local events being deleted by the [Purge History admin API](https://element-hq.github.io/synapse/v1.155/admin_api/purge_history_api.html) despite `delete_local_events` being set to false, in room versions other than 1 and 2.
|
||||
@@ -1,3 +0,0 @@
|
||||
The `GET /_matrix/client/unstable/org.matrix.msc1763/retention/configuration` endpoint is now provided when retention
|
||||
is enabled and `experimental_features.msc1763_enabled` is enabled, based on
|
||||
[MSC1763](https://github.com/matrix-org/matrix-spec-proposals/pull/1763).
|
||||
@@ -1 +0,0 @@
|
||||
Add `.ruff_cache/` directory to `.gitignore`.
|
||||
@@ -1 +0,0 @@
|
||||
Provide remote servers a way to find out about an event created during the remote join handshake. Contributed by @FrenchGithubUser and @jason-famedly @ Famedly.
|
||||
@@ -1 +0,0 @@
|
||||
Provide remote servers a way to find out about an event created during the remote join handshake. Contributed by @FrenchGithubUser and @jason-famedly @ Famedly.
|
||||
@@ -1 +0,0 @@
|
||||
Bump `poetry` in CI from `2.2.1` to `2.4.1`.
|
||||
@@ -1 +0,0 @@
|
||||
Split out `deferred` and `tokio_runtime` to their own Rust modules.
|
||||
@@ -1 +0,0 @@
|
||||
Make simple_select_one_onecol_txn() more helpful by naming the table of the select - as all other query wrapper functions already did.
|
||||
@@ -1 +0,0 @@
|
||||
Add experimental support for [MSC4491: Invite reasons in room creation](https://github.com/matrix-org/matrix-spec-proposals/pull/4491).
|
||||
@@ -1 +0,0 @@
|
||||
Bump `poetry` in CI from `2.2.1` to `2.4.1`.
|
||||
@@ -0,0 +1 @@
|
||||
Change the [MSC3814](https://github.com/matrix-org/matrix-spec-proposals/pull/3814) dehydrated device `/events` endpoint from `POST` to `GET`.
|
||||
Vendored
+3
-2
@@ -1,8 +1,9 @@
|
||||
matrix-synapse-py3 (1.155.0+nmu1) UNRELEASED; urgency=medium
|
||||
matrix-synapse-py3 (1.156.0~rc1) stable; urgency=medium
|
||||
|
||||
* Bump poetry from 2.2.1 to 2.4.1.
|
||||
* New Synapse release 1.156.0rc1.
|
||||
|
||||
-- Synapse Packaging team <work@izzy> Wed, 24 Jun 2026 13:10:00 +0100
|
||||
-- Synapse Packaging team <packages@matrix.org> Tue, 30 Jun 2026 14:37:46 +0100
|
||||
|
||||
matrix-synapse-py3 (1.155.0) stable; urgency=medium
|
||||
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
[project]
|
||||
name = "matrix-synapse"
|
||||
version = "1.155.0"
|
||||
version = "1.156.0rc1"
|
||||
description = "Homeserver for the Matrix decentralised comms protocol"
|
||||
readme = "README.rst"
|
||||
authors = [
|
||||
|
||||
@@ -37,7 +37,7 @@ use crate::{
|
||||
json::AllowMissing,
|
||||
};
|
||||
|
||||
/// Version-specific fields for room version 11.
|
||||
/// Version-specific fields for room version 12+.
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct EventFormatV4 {
|
||||
#[serde(
|
||||
@@ -57,6 +57,8 @@ impl EventFormatV4 {
|
||||
bail!("v4 events must not have an explicit event_id");
|
||||
}
|
||||
|
||||
validate_optional_room_id(self.room_id.as_ref_opt(), common_fields)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ use pyo3::PyResult;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::events::constants::event_type::M_ROOM_CREATE;
|
||||
use crate::events::formats::v4::get_room_id_for_optional_room_id;
|
||||
use crate::events::formats::v4::{get_room_id_for_optional_room_id, validate_optional_room_id};
|
||||
use crate::events::formats::EventCommonFields;
|
||||
use crate::events::Event;
|
||||
use crate::json::AllowMissing;
|
||||
@@ -62,6 +62,8 @@ impl EventFormatVMSC4242 {
|
||||
bail!("MSC4242 events must not have an explicit event_id");
|
||||
}
|
||||
|
||||
validate_optional_room_id(self.room_id.as_ref_opt(), common_fields)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
@@ -367,9 +367,14 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
/// Tests to ensure events with overly large values for `depth` are handled appropriately.
|
||||
/// This was added in room version 6 <https://spec.matrix.org/v1.16/rooms/v6/#event-format>.
|
||||
fn test_calculate_event_id_big_int_old_rooms() {
|
||||
/// This is a bit funky, but we test that relaxed `depth` rules are in
|
||||
/// place, even in room versions that enforce strict canonical JSON, as we
|
||||
/// still need to load invalid events from the database even in newer room
|
||||
/// versions. See https://github.com/element-hq/synapse/pull/19816.
|
||||
///
|
||||
/// We still enforce canonicaljson when creating *new* events (see
|
||||
/// `EventValidator` on the python side).
|
||||
fn test_calculate_event_id_big_int_is_relaxed() {
|
||||
let original = json!(
|
||||
{
|
||||
"auth_events":[
|
||||
@@ -407,12 +412,10 @@ mod tests {
|
||||
);
|
||||
|
||||
// These should succeed.
|
||||
let _event_id = calculate_event_id(&original, &RoomVersion::V3).unwrap();
|
||||
let _event_id = calculate_event_id(&original, &RoomVersion::V4).unwrap();
|
||||
let _event_id = calculate_event_id(&original, &RoomVersion::V5).unwrap();
|
||||
|
||||
// These should not succeed.
|
||||
let versions = [
|
||||
RoomVersion::V3,
|
||||
RoomVersion::V4,
|
||||
RoomVersion::V5,
|
||||
RoomVersion::V6,
|
||||
RoomVersion::V7,
|
||||
RoomVersion::V8,
|
||||
@@ -422,7 +425,7 @@ mod tests {
|
||||
RoomVersion::V12,
|
||||
];
|
||||
for version in versions {
|
||||
let _event_id = calculate_event_id(&original, &version).unwrap_err();
|
||||
let _event_id = calculate_event_id(&original, &version).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+5
-7
@@ -105,8 +105,6 @@ pub mod allow_missing {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::assert_matches;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use super::*;
|
||||
@@ -126,12 +124,12 @@ mod tests {
|
||||
let json = r#"{"value":42}"#;
|
||||
let deserialized: TestStruct = serde_json::from_str(json).unwrap();
|
||||
assert!(deserialized.value.is_some());
|
||||
assert_matches!(deserialized.value, AllowMissing::Some(42));
|
||||
assert!(matches!(deserialized.value, AllowMissing::Some(42)));
|
||||
|
||||
let json = r#"{}"#;
|
||||
let deserialized: TestStruct = serde_json::from_str(json).unwrap();
|
||||
assert!(deserialized.value.is_absent());
|
||||
assert_matches!(deserialized.value, AllowMissing::Absent);
|
||||
assert!(matches!(deserialized.value, AllowMissing::Absent));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -203,16 +201,16 @@ mod tests {
|
||||
let json = r#"{"value":42}"#;
|
||||
let deserialized: TestStructOption = serde_json::from_str(json).unwrap();
|
||||
assert!(deserialized.value.is_some());
|
||||
assert_matches!(deserialized.value, AllowMissing::Some(Some(42)));
|
||||
assert!(matches!(deserialized.value, AllowMissing::Some(Some(42))));
|
||||
|
||||
let json = r#"{"value":null}"#;
|
||||
let deserialized: TestStructOption = serde_json::from_str(json).unwrap();
|
||||
assert!(deserialized.value.is_some());
|
||||
assert_matches!(deserialized.value, AllowMissing::Some(None));
|
||||
assert!(matches!(deserialized.value, AllowMissing::Some(None)));
|
||||
|
||||
let json = r#"{}"#;
|
||||
let deserialized: TestStructOption = serde_json::from_str(json).unwrap();
|
||||
assert!(deserialized.value.is_absent());
|
||||
assert_matches!(deserialized.value, AllowMissing::Absent);
|
||||
assert!(matches!(deserialized.value, AllowMissing::Absent));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
$schema: https://element-hq.github.io/synapse/latest/schema/v1/meta.schema.json
|
||||
$id: https://element-hq.github.io/synapse/schema/synapse/v1.155/synapse-config.schema.json
|
||||
$id: https://element-hq.github.io/synapse/schema/synapse/v1.156/synapse-config.schema.json
|
||||
type: object
|
||||
properties:
|
||||
modules:
|
||||
|
||||
@@ -33,6 +33,7 @@ from synapse.http.servlet import (
|
||||
RestServlet,
|
||||
parse_and_validate_json_object_from_request,
|
||||
parse_integer,
|
||||
parse_string,
|
||||
)
|
||||
from synapse.http.site import SynapseRequest
|
||||
from synapse.rest.client._base import client_patterns, interactive_auth_handler
|
||||
@@ -249,17 +250,49 @@ class DehydratedDeviceEventsServlet(RestServlet):
|
||||
self.auth = hs.get_auth()
|
||||
self.store = hs.get_datastores().main
|
||||
|
||||
async def on_GET(
|
||||
self, request: SynapseRequest, device_id: str
|
||||
) -> tuple[int, JsonDict]:
|
||||
requester = await self.auth.get_user_by_req(request)
|
||||
|
||||
next_batch = parse_string(request, "next_batch")
|
||||
limit = parse_integer(request, "limit", 100)
|
||||
|
||||
msgs = await self.message_handler.get_events_for_dehydrated_device(
|
||||
requester=requester,
|
||||
device_id=device_id,
|
||||
since_token=next_batch,
|
||||
limit=limit,
|
||||
)
|
||||
|
||||
return 200, msgs
|
||||
|
||||
class PostBody(RequestBodyModel):
|
||||
"""
|
||||
This is deprecated: you should use GET instead.
|
||||
|
||||
The POST version is provided temporarily for backwards compatibility
|
||||
with a previous unstable draft of MSC3814.
|
||||
"""
|
||||
|
||||
next_batch: StrictStr | None = None
|
||||
|
||||
async def on_POST(
|
||||
self, request: SynapseRequest, device_id: str
|
||||
) -> tuple[int, JsonDict]:
|
||||
"""
|
||||
This is deprecated: you should use GET instead.
|
||||
|
||||
The POST version is provided temporarily for backwards compatibility
|
||||
with a previous unstable draft of MSC3814.
|
||||
"""
|
||||
|
||||
requester = await self.auth.get_user_by_req(request)
|
||||
|
||||
next_batch = parse_and_validate_json_object_from_request(
|
||||
request, self.PostBody
|
||||
).next_batch
|
||||
|
||||
limit = parse_integer(request, "limit", 100)
|
||||
|
||||
msgs = await self.message_handler.get_events_for_dehydrated_device(
|
||||
|
||||
@@ -196,6 +196,16 @@ class MasSyncDevicesResource(MasBaseResource):
|
||||
current_devices_list = set(current_devices.keys())
|
||||
target_device_list = set(body.devices)
|
||||
|
||||
# Exclude the dehydrated device (MSC3814): it has no MAS session, so MAS
|
||||
# never lists it in the target set and the reconciliation below would
|
||||
# otherwise treat it as extra and delete it. This mirrors the admin
|
||||
# devices API and MAS's own legacy device-sync path, which both skip it.
|
||||
dehydrated_device = await self.device_handler.get_dehydrated_device(
|
||||
user_id=str(user_id)
|
||||
)
|
||||
if dehydrated_device is not None:
|
||||
current_devices_list.discard(dehydrated_device[0])
|
||||
|
||||
to_add = target_device_list - current_devices_list
|
||||
to_delete = current_devices_list - target_device_list
|
||||
|
||||
|
||||
@@ -11,7 +11,12 @@
|
||||
# See the GNU Affero General Public License for more details:
|
||||
# <https://www.gnu.org/licenses/agpl-3.0.html>.
|
||||
#
|
||||
from synapse.api.room_versions import RoomVersions
|
||||
from synapse.api.errors import Codes, SynapseError
|
||||
from synapse.api.room_versions import (
|
||||
KNOWN_ROOM_VERSIONS,
|
||||
EventFormatVersions,
|
||||
RoomVersions,
|
||||
)
|
||||
from synapse.events import make_event_from_dict
|
||||
from synapse.events.validator import EventValidator
|
||||
|
||||
@@ -45,3 +50,46 @@ class EventValidatorTestCase(HomeserverTestCase):
|
||||
)
|
||||
|
||||
EventValidator().validate_new(event, self.hs.config)
|
||||
|
||||
def test_validate_new_rejects_big_depth_for_strict_canonicaljson_rooms(
|
||||
self,
|
||||
) -> None:
|
||||
"""
|
||||
Test that `EventValidator.validate_new` rejects events with integers outside the
|
||||
canonical JSON range, in room versions which enforce it (v6+).
|
||||
"""
|
||||
for room_version in KNOWN_ROOM_VERSIONS.values():
|
||||
with self.subTest(room_version=room_version.identifier):
|
||||
event_dict = {
|
||||
"room_id": "!room:test",
|
||||
"type": "m.room.message",
|
||||
"sender": "@alice:example.com",
|
||||
"content": {
|
||||
"msgtype": "m.text",
|
||||
"body": "hello",
|
||||
},
|
||||
"auth_events": [],
|
||||
"prev_events": [],
|
||||
"hashes": {"sha256": "aGVsbG8="},
|
||||
"signatures": {},
|
||||
"depth": 2**53,
|
||||
"origin_server_ts": 1000,
|
||||
}
|
||||
|
||||
if room_version.event_format == EventFormatVersions.ROOM_V1_V2:
|
||||
event_dict["event_id"] = "$event:test"
|
||||
|
||||
event = make_event_from_dict(
|
||||
event_dict,
|
||||
room_version=room_version,
|
||||
)
|
||||
|
||||
# Check if this room version enforces strict canonical json.
|
||||
if room_version.strict_canonicaljson:
|
||||
with self.assertRaises(SynapseError) as cm:
|
||||
EventValidator().validate_new(event, self.hs.config)
|
||||
|
||||
self.assertEqual(cm.exception.errcode, Codes.BAD_JSON)
|
||||
self.assertEqual(cm.exception.msg, "JSON integer out of range")
|
||||
else:
|
||||
EventValidator().validate_new(event, self.hs.config)
|
||||
|
||||
@@ -224,9 +224,8 @@ class DehydratedDeviceTestCase(unittest.HomeserverTestCase):
|
||||
|
||||
# make sure we can fetch the message with our dehydrated device id
|
||||
channel = self.make_request(
|
||||
"POST",
|
||||
"GET",
|
||||
f"_matrix/client/unstable/org.matrix.msc3814.v1/dehydrated_device/{device_id}/events",
|
||||
content={},
|
||||
access_token=token,
|
||||
shorthand=False,
|
||||
)
|
||||
@@ -236,9 +235,8 @@ class DehydratedDeviceTestCase(unittest.HomeserverTestCase):
|
||||
|
||||
# fetch messages again and make sure that the message was not deleted
|
||||
channel = self.make_request(
|
||||
"POST",
|
||||
"GET",
|
||||
f"_matrix/client/unstable/org.matrix.msc3814.v1/dehydrated_device/{device_id}/events",
|
||||
content={},
|
||||
access_token=token,
|
||||
shorthand=False,
|
||||
)
|
||||
@@ -248,11 +246,9 @@ class DehydratedDeviceTestCase(unittest.HomeserverTestCase):
|
||||
|
||||
# make sure fetching messages with next batch token works - there are no unfetched
|
||||
# messages so we should receive an empty array
|
||||
content = {"next_batch": next_batch_token}
|
||||
channel = self.make_request(
|
||||
"POST",
|
||||
f"_matrix/client/unstable/org.matrix.msc3814.v1/dehydrated_device/{device_id}/events",
|
||||
content=content,
|
||||
"GET",
|
||||
f"_matrix/client/unstable/org.matrix.msc3814.v1/dehydrated_device/{device_id}/events?next_batch={next_batch_token}",
|
||||
access_token=token,
|
||||
shorthand=False,
|
||||
)
|
||||
|
||||
@@ -546,6 +546,48 @@ class MasSyncDevicesResource(BaseTestCase):
|
||||
devices = self.get_success(store.get_devices_by_user(str(self.alice_user_id)))
|
||||
self.assertEqual(set(devices.keys()), {"DEVICE1"})
|
||||
|
||||
def test_sync_devices_preserves_dehydrated_device(self) -> None:
|
||||
# Store a dehydrated device (MSC3814). It has no MAS session, so it is
|
||||
# never part of the target device list, but it must survive a sync.
|
||||
device_handler = self.hs.get_device_handler()
|
||||
dehydrated_device_id = self.get_success(
|
||||
device_handler.store_dehydrated_device(
|
||||
user_id=str(self.alice_user_id),
|
||||
device_id=None,
|
||||
device_data={"device_data": {"foo": "bar"}},
|
||||
initial_device_display_name="dehydrated device",
|
||||
keys_for_device={},
|
||||
)
|
||||
)
|
||||
|
||||
# Sync down to a single real device. The dehydrated device is not in the
|
||||
# target list, but must not be deleted.
|
||||
channel = self.make_request(
|
||||
"POST",
|
||||
"/_synapse/mas/sync_devices",
|
||||
shorthand=False,
|
||||
access_token=self.SHARED_SECRET,
|
||||
content={
|
||||
"localpart": "alice",
|
||||
"devices": ["DEVICE1"],
|
||||
},
|
||||
)
|
||||
|
||||
self.assertEqual(channel.code, 200, channel.json_body)
|
||||
self.assertEqual(channel.json_body, {})
|
||||
|
||||
# The real devices are reconciled, but the dehydrated device survives.
|
||||
store = self.hs.get_datastores().main
|
||||
devices = self.get_success(store.get_devices_by_user(str(self.alice_user_id)))
|
||||
self.assertEqual(set(devices.keys()), {"DEVICE1", dehydrated_device_id})
|
||||
|
||||
# And it is still registered as the dehydrated device.
|
||||
dehydrated = self.get_success(
|
||||
device_handler.get_dehydrated_device(str(self.alice_user_id))
|
||||
)
|
||||
assert dehydrated is not None
|
||||
self.assertEqual(dehydrated[0], dehydrated_device_id)
|
||||
|
||||
def test_sync_devices_add_and_delete(self) -> None:
|
||||
# Sync with a mix of additions and deletions
|
||||
channel = self.make_request(
|
||||
|
||||
Reference in New Issue
Block a user