Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add support for the dehydrated devices endpoints (#1605)
This patch adds support for the endpoints used in [MSC3814]. One notable change to the MSC here is that the PUT endpoint uploads the device and one-time keys as well. [MSC3814]: matrix-org/matrix-spec-proposals#3814 Co-authored-by: Kévin Commaille <76261501+zecakeh@users.noreply.github.com>
- Loading branch information
Showing
8 changed files
with
347 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
//! Endpoints for managing dehydrated devices. | ||
|
||
use ruma_common::serde::StringEnum; | ||
use serde::{Deserialize, Serialize}; | ||
|
||
use crate::PrivOwnedStr; | ||
|
||
pub mod delete_dehydrated_device; | ||
pub mod get_dehydrated_device; | ||
pub mod get_events; | ||
pub mod put_dehydrated_device; | ||
|
||
/// Data for a dehydrated device. | ||
#[derive(Clone, Debug, Deserialize, Serialize)] | ||
#[serde(try_from = "Helper", into = "Helper")] | ||
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)] | ||
pub enum DehydratedDeviceData { | ||
/// The `org.matrix.msc3814.v1.olm` variant of a dehydrated device. | ||
V1(DehydratedDeviceV1), | ||
} | ||
|
||
impl DehydratedDeviceData { | ||
/// Get the algorithm this dehydrated device uses. | ||
pub fn algorithm(&self) -> DeviceDehydrationAlgorithm { | ||
match self { | ||
DehydratedDeviceData::V1(_) => DeviceDehydrationAlgorithm::V1, | ||
} | ||
} | ||
} | ||
|
||
/// The `org.matrix.msc3814.v1.olm` variant of a dehydrated device. | ||
#[derive(Clone, Debug)] | ||
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)] | ||
pub struct DehydratedDeviceV1 { | ||
/// The pickle of the `Olm` account of the device. | ||
/// | ||
/// The pickle will contain the private parts of the long-term identity keys of the device as | ||
/// well as a collection of one-time keys. | ||
pub device_pickle: String, | ||
} | ||
|
||
impl DehydratedDeviceV1 { | ||
/// Create a [`DehydratedDeviceV1`] struct from a device pickle. | ||
pub fn new(device_pickle: String) -> Self { | ||
Self { device_pickle } | ||
} | ||
} | ||
|
||
/// The algorithms used for dehydrated devices. | ||
#[doc = include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/src/doc/string_enum.md"))] | ||
#[derive(Clone, PartialEq, Eq, StringEnum)] | ||
#[non_exhaustive] | ||
pub enum DeviceDehydrationAlgorithm { | ||
/// The `org.matrix.msc3814.v1.olm` device dehydration algorithm. | ||
#[ruma_enum(rename = "org.matrix.msc3814.v1.olm")] | ||
V1, | ||
#[doc(hidden)] | ||
_Custom(PrivOwnedStr), | ||
} | ||
|
||
#[derive(Deserialize, Serialize)] | ||
struct Helper { | ||
algorithm: DeviceDehydrationAlgorithm, | ||
device_pickle: String, | ||
} | ||
|
||
impl TryFrom<Helper> for DehydratedDeviceData { | ||
type Error = serde_json::Error; | ||
|
||
fn try_from(value: Helper) -> Result<Self, Self::Error> { | ||
match value.algorithm { | ||
DeviceDehydrationAlgorithm::V1 => Ok(DehydratedDeviceData::V1(DehydratedDeviceV1 { | ||
device_pickle: value.device_pickle, | ||
})), | ||
_ => Err(serde::de::Error::custom("Unsupported device dehydration algorithm.")), | ||
} | ||
} | ||
} | ||
|
||
impl From<DehydratedDeviceData> for Helper { | ||
fn from(value: DehydratedDeviceData) -> Self { | ||
let algorithm = value.algorithm(); | ||
|
||
match value { | ||
DehydratedDeviceData::V1(d) => Self { algorithm, device_pickle: d.device_pickle }, | ||
} | ||
} | ||
} |
48 changes: 48 additions & 0 deletions
48
crates/ruma-client-api/src/dehydrated_device/delete_dehydrated_device.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
//! `DELETE /_matrix/client/*/dehydrated_device/` | ||
//! | ||
//! Delete a dehydrated device. | ||
|
||
pub mod unstable { | ||
//! `msc3814` ([MSC]) | ||
//! | ||
//! [MSC]: https://github.com/matrix-org/matrix-spec-proposals/pull/3814 | ||
|
||
use ruma_common::{ | ||
api::{request, response, Metadata}, | ||
metadata, OwnedDeviceId, | ||
}; | ||
|
||
const METADATA: Metadata = metadata! { | ||
method: DELETE, | ||
rate_limited: false, | ||
authentication: AccessToken, | ||
history: { | ||
unstable => "/_matrix/client/unstable/org.matrix.msc3814.v1/dehydrated_device", | ||
} | ||
}; | ||
|
||
/// Request type for the `DELETE` `dehydrated_device` endpoint. | ||
#[request(error = crate::Error)] | ||
pub struct Request {} | ||
|
||
/// Request type for the `DELETE` `dehydrated_device` endpoint. | ||
#[response(error = crate::Error)] | ||
pub struct Response { | ||
/// The unique ID of the device that was deleted. | ||
pub device_id: OwnedDeviceId, | ||
} | ||
|
||
impl Request { | ||
/// Creates a new empty `Request`. | ||
pub fn new() -> Self { | ||
Self {} | ||
} | ||
} | ||
|
||
impl Response { | ||
/// Creates a new `Response` with the given device ID. | ||
pub fn new(device_id: OwnedDeviceId) -> Self { | ||
Self { device_id } | ||
} | ||
} | ||
} |
54 changes: 54 additions & 0 deletions
54
crates/ruma-client-api/src/dehydrated_device/get_dehydrated_device.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
//! `GET /_matrix/client/*/dehydrated_device/` | ||
//! | ||
//! Get a dehydrated device for rehydration. | ||
|
||
pub mod unstable { | ||
//! `msc3814` ([MSC]) | ||
//! | ||
//! [MSC]: https://github.com/matrix-org/matrix-spec-proposals/pull/3814 | ||
|
||
use ruma_common::{ | ||
api::{request, response, Metadata}, | ||
metadata, | ||
serde::Raw, | ||
OwnedDeviceId, | ||
}; | ||
|
||
use crate::dehydrated_device::DehydratedDeviceData; | ||
|
||
const METADATA: Metadata = metadata! { | ||
method: GET, | ||
rate_limited: false, | ||
authentication: AccessToken, | ||
history: { | ||
unstable => "/_matrix/client/unstable/org.matrix.msc3814.v1/dehydrated_device", | ||
} | ||
}; | ||
|
||
/// Request type for the `GET` `dehydrated_device` endpoint. | ||
#[request(error = crate::Error)] | ||
pub struct Request {} | ||
|
||
/// Request type for the `GET` `dehydrated_device` endpoint. | ||
#[response(error = crate::Error)] | ||
pub struct Response { | ||
/// The unique ID of the device. | ||
pub device_id: OwnedDeviceId, | ||
/// Information about the device. | ||
pub device_data: Raw<DehydratedDeviceData>, | ||
} | ||
|
||
impl Request { | ||
/// Creates a new empty `Request`. | ||
pub fn new() -> Self { | ||
Self {} | ||
} | ||
} | ||
|
||
impl Response { | ||
/// Creates a new `Response` with the given device ID and device data. | ||
pub fn new(device_id: OwnedDeviceId, device_data: Raw<DehydratedDeviceData>) -> Self { | ||
Self { device_id, device_data } | ||
} | ||
} | ||
} |
65 changes: 65 additions & 0 deletions
65
crates/ruma-client-api/src/dehydrated_device/get_events.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
//! `POST /_matrix/client/*/dehydrated_device/{device_id}/events` | ||
//! | ||
//! Get to-device events for a dehydrated device. | ||
|
||
pub mod unstable { | ||
//! `msc3814` ([MSC]) | ||
//! | ||
//! [MSC]: https://github.com/matrix-org/matrix-spec-proposals/pull/3814 | ||
|
||
use ruma_common::{ | ||
api::{request, response, Metadata}, | ||
events::AnyToDeviceEvent, | ||
metadata, | ||
serde::Raw, | ||
OwnedDeviceId, | ||
}; | ||
|
||
const METADATA: Metadata = metadata! { | ||
method: POST, | ||
rate_limited: false, | ||
authentication: AccessToken, | ||
history: { | ||
unstable => "/_matrix/client/unstable/org.matrix.msc3814.v1/dehydrated_device/:device_id/events", | ||
} | ||
}; | ||
|
||
/// Request type for the `dehydrated_device/{device_id}/events` endpoint. | ||
#[request(error = crate::Error)] | ||
pub struct Request { | ||
/// The unique ID of the device for which we would like to fetch events. | ||
#[ruma_api(path)] | ||
pub device_id: OwnedDeviceId, | ||
/// A point in time to continue getting events from. | ||
/// | ||
/// Should be a token from the `next_batch` field of a previous `/events` | ||
/// request. | ||
#[serde(skip_serializing_if = "Option::is_none")] | ||
pub next_batch: Option<String>, | ||
} | ||
|
||
/// Request type for the `dehydrated_device/{device_id}/events` endpoint. | ||
#[response(error = crate::Error)] | ||
pub struct Response { | ||
/// The batch token to supply in the `since` param of the next `/events` request. Will be | ||
/// none if no further events can be found. | ||
pub next_batch: Option<String>, | ||
|
||
/// Messages sent directly between devices. | ||
pub events: Vec<Raw<AnyToDeviceEvent>>, | ||
} | ||
|
||
impl Request { | ||
/// Create a new request. | ||
pub fn new(device_id: OwnedDeviceId) -> Self { | ||
Self { device_id, next_batch: None } | ||
} | ||
} | ||
|
||
impl Response { | ||
/// Create a new response with the given events. | ||
pub fn new(events: Vec<Raw<AnyToDeviceEvent>>) -> Self { | ||
Self { next_batch: None, events } | ||
} | ||
} | ||
} |
87 changes: 87 additions & 0 deletions
87
crates/ruma-client-api/src/dehydrated_device/put_dehydrated_device.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
//! `PUT /_matrix/client/*/dehydrated_device/` | ||
//! | ||
//! Uploads a dehydrated device to the homeserver. | ||
|
||
pub mod unstable { | ||
//! `msc3814` ([MSC]) | ||
//! | ||
//! [MSC]: https://github.com/matrix-org/matrix-spec-proposals/pull/3814 | ||
|
||
use std::collections::BTreeMap; | ||
|
||
use ruma_common::{ | ||
api::{request, response, Metadata}, | ||
encryption::{DeviceKeys, OneTimeKey}, | ||
metadata, | ||
serde::Raw, | ||
OwnedDeviceId, OwnedDeviceKeyId, | ||
}; | ||
|
||
use crate::dehydrated_device::DehydratedDeviceData; | ||
|
||
const METADATA: Metadata = metadata! { | ||
method: PUT, | ||
rate_limited: false, | ||
authentication: AccessToken, | ||
history: { | ||
unstable => "/_matrix/client/unstable/org.matrix.msc3814.v1/dehydrated_device", | ||
} | ||
}; | ||
|
||
/// Request type for the `PUT` `dehydrated_device` endpoint. | ||
#[request(error = crate::Error)] | ||
pub struct Request { | ||
/// The unique ID of the device. | ||
pub device_id: OwnedDeviceId, | ||
|
||
/// The display name of the device. | ||
pub initial_device_display_name: Option<String>, | ||
|
||
/// The data of the dehydrated device, containing the serialized and encrypted private | ||
/// parts of the [`DeviceKeys`]. | ||
pub device_data: Raw<DehydratedDeviceData>, | ||
|
||
/// Identity keys for the dehydrated device. | ||
pub device_keys: Raw<DeviceKeys>, | ||
|
||
/// One-time public keys for "pre-key" messages. | ||
#[serde(default, skip_serializing_if = "BTreeMap::is_empty")] | ||
pub one_time_keys: BTreeMap<OwnedDeviceKeyId, Raw<OneTimeKey>>, | ||
|
||
/// Fallback public keys for "pre-key" messages. | ||
#[serde(default, skip_serializing_if = "BTreeMap::is_empty")] | ||
pub fallback_keys: BTreeMap<OwnedDeviceKeyId, Raw<OneTimeKey>>, | ||
} | ||
|
||
/// Response type for the `upload_keys` endpoint. | ||
#[response(error = crate::Error)] | ||
pub struct Response { | ||
/// The unique ID of the device. | ||
pub device_id: OwnedDeviceId, | ||
} | ||
|
||
impl Request { | ||
/// Creates a new Request. | ||
pub fn new( | ||
device_id: OwnedDeviceId, | ||
device_data: Raw<DehydratedDeviceData>, | ||
device_keys: Raw<DeviceKeys>, | ||
) -> Self { | ||
Self { | ||
device_id, | ||
device_data, | ||
device_keys, | ||
initial_device_display_name: None, | ||
one_time_keys: Default::default(), | ||
fallback_keys: Default::default(), | ||
} | ||
} | ||
} | ||
|
||
impl Response { | ||
/// Creates a new `Response` with the given one time key counts. | ||
pub fn new(device_id: OwnedDeviceId) -> Self { | ||
Self { device_id } | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters