palpo_core/client/
backup.rs

1/// Endpoints for server-side key backups.
2use std::collections::BTreeMap;
3
4use salvo::prelude::*;
5use serde::{Deserialize, Serialize};
6
7use crate::serde::{Base64, RawJson};
8use crate::{OwnedDeviceKeyId, OwnedRoomId, OwnedSessionId, OwnedUserId, RawJsonValue};
9
10/// A wrapper around a mapping of session IDs to key data.
11#[derive(ToSchema, Clone, Debug, Serialize, Deserialize)]
12pub struct RoomKeyBackup {
13    /// A map of session IDs to key data.
14    pub sessions: BTreeMap<OwnedSessionId, KeyBackupData>,
15}
16
17impl RoomKeyBackup {
18    /// Creates a new `RoomKeyBackup` with the given sessions.
19    pub fn new(sessions: BTreeMap<OwnedSessionId, KeyBackupData>) -> Self {
20        Self { sessions }
21    }
22}
23
24/// The algorithm used for storing backups.
25#[derive(ToSchema, Clone, Debug, Serialize, Deserialize)]
26#[serde(tag = "algorithm", content = "auth_data")]
27pub enum BackupAlgorithm {
28    /// `m.megolm_backup.v1.curve25519-aes-sha2` backup algorithm.
29    #[serde(rename = "m.megolm_backup.v1.curve25519-aes-sha2")]
30    MegolmBackupV1Curve25519AesSha2 {
31        /// The curve25519 public key used to encrypt the backups, encoded in unpadded base64.
32        #[salvo(schema(value_type = String))]
33        public_key: Base64,
34
35        /// Signatures of the auth_data as Signed JSON.
36        signatures: BTreeMap<OwnedUserId, BTreeMap<OwnedDeviceKeyId, String>>,
37    },
38}
39
40/// Information about the backup key.
41///
42/// To create an instance of this type, first create a [`KeyBackupDataInit`] and convert it via
43/// `KeyBackupData::from` / `.into()`.
44#[derive(ToSchema, Clone, Debug, Serialize, Deserialize)]
45pub struct KeyBackupData {
46    /// The index of the first message in the session that the key can decrypt.
47    pub first_message_index: u64,
48
49    /// The number of times this key has been forwarded via key-sharing between devices.
50    pub forwarded_count: u64,
51
52    /// Whether the device backing up the key verified the device that the key is from.
53    pub is_verified: bool,
54
55    /// Encrypted data about the session.
56    pub session_data: RawJson<EncryptedSessionData>,
57}
58
59/// The encrypted algorithm-dependent data for backups.
60///
61/// To create an instance of this type.
62#[derive(ToSchema, Clone, Debug, Serialize, Deserialize)]
63pub struct EncryptedSessionData {
64    /// Unpadded base64-encoded public half of the ephemeral key.
65    #[salvo(schema(value_type = String))]
66    pub ephemeral: Base64,
67
68    /// Ciphertext, encrypted using AES-CBC-256 with PKCS#7 padding, encoded in base64.
69    #[salvo(schema(value_type = String))]
70    pub ciphertext: Base64,
71
72    /// First 8 bytes of MAC key, encoded in base64.
73    #[salvo(schema(value_type = String))]
74    pub mac: Base64,
75}
76
77/// `PUT /_matrix/client/*/room_keys/keys/{room_id}`
78///
79/// Store keys in the backup for a room.
80
81/// `/v3/` ([spec])
82///
83/// [spec]: https://spec.matrix.org/latest/client-server-api/#put_matrixclientv3room_keyskeysroomid
84
85// const METADATA: Metadata = metadata! {
86//     method: PUT,
87//     rate_limited: true,
88//     authentication: AccessToken,
89//     history: {
90//         unstable => "/_matrix/client/unstable/room_keys/keys/:room_id",
91//         1.0 => "/_matrix/client/r0/room_keys/keys/:room_id",
92//         1.1 => "/_matrix/client/v3/room_keys/keys/:room_id",
93//     }
94// };
95/// Response type for the `add_backup_keys_for_room` endpoint.
96
97#[derive(ToSchema, Serialize, Debug)]
98pub struct ModifyKeysResBody {
99    /// An opaque string representing stored keys in the backup.
100    ///
101    /// Clients can compare it with the etag value they received in the request of their last
102    /// key storage request.
103    pub etag: String,
104
105    /// The number of keys stored in the backup.
106    pub count: u64,
107}
108
109impl ModifyKeysResBody {
110    /// Creates an new `Response` with the given etag and count.
111    pub fn new(etag: String, count: u64) -> Self {
112        Self { etag, count }
113    }
114}
115
116/// `PUT /_matrix/client/*/room_keys/keys/{room_id}/{sessionId}`
117///
118/// Store keys in the backup for a session.
119/// `/v3/` ([spec])
120///
121/// [spec]: https://spec.matrix.org/latest/client-server-api/#put_matrixclientv3room_keyskeysroomidsessionid
122
123// const METADATA: Metadata = metadata! {
124//     method: PUT,
125//     rate_limited: true,
126//     authentication: AccessToken,
127//     history: {
128//         unstable => "/_matrix/client/unstable/room_keys/keys/:room_id/:session_id",
129//         1.0 => "/_matrix/client/r0/room_keys/keys/:room_id/:session_id",
130//         1.1 => "/_matrix/client/v3/room_keys/keys/:room_id/:session_id",
131//     }
132// };
133
134/// Request type for the `add_backup_keys_for_session` endpoint.
135#[derive(ToSchema, Deserialize, Debug)]
136pub struct AddKeysForSessionReqBody(
137    /// The key information to store.
138    #[salvo(schema(value_type = Object, additional_properties = true))]
139    pub KeyBackupData,
140);
141
142/// `POST /_matrix/client/*/room_keys/version`
143///
144/// Create a new backup version.
145/// `/v3/` ([spec])
146///
147/// [spec]: https://spec.matrix.org/latest/client-server-api/#post_matrixclientv3room_keysversion
148
149// const METADATA: Metadata = metadata! {
150//     method: POST,
151//     rate_limited: true,
152//     authentication: AccessToken,
153//     history: {
154//         unstable => "/_matrix/client/unstable/room_keys/version",
155//         1.1 => "/_matrix/client/v3/room_keys/version",
156//     }
157// };
158
159/// Request type for the `create_backup_version` endpoint.
160#[derive(ToSchema, Deserialize, Debug)]
161pub struct CreateVersionReqBody(
162    /// The algorithm used for storing backups.
163    pub RawJson<BackupAlgorithm>,
164);
165
166/// Response type for the `create_backup_version` endpoint.
167
168#[derive(ToSchema, Serialize, Debug)]
169pub struct CreateVersionResBody {
170    /// The backup version.
171    pub version: String,
172}
173impl CreateVersionResBody {
174    /// Creates a new `Response` with the given version.
175    pub fn new(version: String) -> Self {
176        Self { version }
177    }
178}
179
180/// `PUT /_matrix/client/*/room_keys/keys`
181///
182/// Store keys in the backup.
183/// `/v3/` ([spec])
184///
185/// [spec]: https://spec.matrix.org/latest/client-server-api/#put_matrixclientv3room_keyskeys
186// const METADATA: Metadata = metadata! {
187//     method: PUT,
188//     rate_limited: true,
189//     authentication: AccessToken,
190//     history: {
191//         unstable => "/_matrix/client/unstable/room_keys/keys",
192//         1.1 => "/_matrix/client/v3/room_keys/keys",
193//     }
194// };
195
196/// Request type for the `add_backup_keys` endpoint.
197#[derive(ToSchema, Deserialize, Debug)]
198pub struct AddKeysReqBody {
199    /// A map of room IDs to session IDs to key data to store.
200    pub rooms: BTreeMap<OwnedRoomId, RoomKeyBackup>,
201}
202
203/// `DELETE /_matrix/client/*/room_keys/keys/{room_id}`
204///
205/// Delete keys from a backup for a given room.
206/// `/v3/` ([spec])
207///
208/// [spec]: https://spec.matrix.org/latest/client-server-api/#delete_matrixclientv3room_keyskeysroomid
209// const METADATA: Metadata = metadata! {
210//     method: DELETE,
211//     rate_limited: true,
212//     authentication: AccessToken,
213//     history: {
214//         unstable => "/_matrix/client/unstable/room_keys/keys/:room_id",
215//         1.0 => "/_matrix/client/r0/room_keys/keys/:room_id",
216//         1.1 => "/_matrix/client/v3/room_keys/keys/:room_id",
217//     }
218// };
219
220/// Request type for the `delete_backup_keys_for_room` endpoint.
221#[derive(ToParameters, Deserialize, Debug)]
222pub struct KeysForRoomReqArgs {
223    /// The backup version from which to delete keys.
224    #[salvo(parameter(parameter_in = Query))]
225    pub version: i64,
226
227    /// The ID of the room to delete keys from.
228    #[salvo(parameter(parameter_in = Path))]
229    pub room_id: OwnedRoomId,
230}
231
232/// `DELETE /_matrix/client/*/room_keys/keys/{room_id}/{sessionId}`
233///
234/// Delete keys from a backup for a given session.
235/// `/v3/` ([spec])
236///
237/// [spec]: https://spec.matrix.org/latest/client-server-api/#delete_matrixclientv3room_keyskeysroomidsessionid
238
239// const METADATA: Metadata = metadata! {
240//     method: DELETE,
241//     rate_limited: true,
242//     authentication: AccessToken,
243//     history: {
244//         unstable => "/_matrix/client/unstable/room_keys/keys/:room_id/:session_id",
245//         1.0 => "/_matrix/client/r0/room_keys/keys/:room_id/:session_id",
246//         1.1 => "/_matrix/client/v3/room_keys/keys/:room_id/:session_id",
247//     }
248// };
249
250/// `DELETE /_matrix/client/*/room_keys/keys`
251///
252/// Delete all keys from a backup.
253/// `/v3/` ([spec])
254///
255/// [spec]: https://spec.matrix.org/latest/client-server-api/#delete_matrixclientv3room_keyskeys
256///
257/// This deletes keys from a backup version, but not the version itself.
258
259// const METADATA: Metadata = metadata! {
260//     method: DELETE,
261//     rate_limited: true,
262//     authentication: AccessToken,
263//     history: {
264//         unstable => "/_matrix/client/unstable/room_keys/keys",
265//         1.0 => "/_matrix/client/r0/room_keys/keys",
266//         1.1 => "/_matrix/client/v3/room_keys/keys",
267//     }
268// };
269
270// /// Request type for the `delete_backup_keys` endpoint.
271// #[derive(ToSchema, Deserialize, Debug)]
272// pub struct DeleteKeysReqBody {
273//     /// The backup version from which to delete keys.
274//     #[salvo(parameter(parameter_in = Query))]
275//     pub version: String,
276// }
277
278/// `GET /_matrix/client/*/room_keys/version/{version}`
279///
280/// Get information about a specific backup.
281/// `/v3/` ([spec])
282///
283/// [spec]: https://spec.matrix.org/latest/client-server-api/#get_matrixclientv3room_keysversionversion
284
285// https://github.com/rust-lang/rust/issues/112615
286
287// const METADATA: Metadata = metadata! {
288//     method: GET,
289//     rate_limited: true,
290//     authentication: AccessToken,
291//     history: {
292//         unstable => "/_matrix/client/unstable/room_keys/version/:version",
293//         1.1 => "/_matrix/client/v3/room_keys/version/:version",
294//     }
295// };
296
297/// Response type for the `get_backup_info` endpoint.
298
299#[derive(ToSchema, Serialize, Debug)]
300pub struct VersionResBody {
301    /// The algorithm used for storing backups.
302    pub algorithm: RawJson<BackupAlgorithm>,
303
304    /// The number of keys stored in the backup.
305    pub count: u64,
306
307    /// An opaque string representing stored keys in the backup.
308    ///
309    /// Clients can compare it with the etag value they received in the request of their last
310    /// key storage request.
311    pub etag: String,
312
313    /// The backup version.
314    pub version: String,
315}
316impl VersionResBody {
317    /// Creates a new `Response` with the given algorithm, key count, etag and version.
318    pub fn new(algorithm: RawJson<BackupAlgorithm>, count: u64, etag: String, version: String) -> Self {
319        Self {
320            algorithm,
321            count,
322            etag,
323            version,
324        }
325    }
326}
327
328// #[derive(Deserialize)]
329// pub(crate) struct ResponseBodyRepr {
330//     pub algorithm: Box<RawJsonValue>,
331//     pub auth_data: Box<RawJsonValue>,
332//     pub count: u64,
333//     pub etag: String,
334//     pub version: String,
335// }
336
337// #[derive(Serialize)]
338// pub(crate) struct RefResponseBodyRepr<'a> {
339//     pub algorithm: &'a RawJsonValue,
340//     pub auth_data: &'a RawJsonValue,
341//     pub count: u64,
342//     pub etag: &'a str,
343//     pub version: &'a str,
344// }
345
346#[derive(Deserialize, Serialize)]
347pub(crate) struct AlgorithmWithData {
348    pub algorithm: Box<RawJsonValue>,
349    pub auth_data: Box<RawJsonValue>,
350}
351
352// impl<'de> Deserialize<'de> for ResponseBody {
353//     fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
354//     where
355//         D: Deserializer<'de>,
356//     {
357//         let ResponseBodyRepr {
358//             algorithm,
359//             auth_data,
360//             count,
361//             etag,
362//             version,
363//         } = ResponseBodyRepr::deserialize(deserializer)?;
364
365//         let algorithm = RawJson::from_json(to_raw_json_value(&AlgorithmWithData { algorithm, auth_data }).unwrap());
366
367//         Ok(Self {
368//             algorithm,
369//             count,
370//             etag,
371//             version,
372//         })
373//     }
374// }
375
376// impl Serialize for ResponseBody {
377//     fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
378//     where
379//         S: serde::Serializer,
380//     {
381//         let ResponseBody {
382//             algorithm,
383//             count,
384//             etag,
385//             version,
386//         } = self;
387//         let AlgorithmWithData { algorithm, auth_data } = algorithm.deserialize_as().map_err(ser::Error::custom)?;
388
389//         let repr = RefResponseBodyRepr {
390//             algorithm: &algorithm,
391//             auth_data: &auth_data,
392//             count: *count,
393//             etag,
394//             version,
395//         };
396
397//         repr.serialize(serializer)
398//     }
399// }
400
401/// `GET /_matrix/client/*/room_keys/keys/{room_id}`
402///
403/// Retrieve sessions from the backup for a given room.
404/// `/v3/` ([spec])
405///
406/// [spec]: https://spec.matrix.org/latest/client-server-api/#get_matrixclientv3room_keyskeysroomid
407
408// const METADATA: Metadata = metadata! {
409//     method: GET,
410//     rate_limited: true,
411//     authentication: AccessToken,
412//     history: {
413//         unstable => "/_matrix/client/unstable/room_keys/keys/:room_id",
414//         1.0 => "/_matrix/client/r0/room_keys/keys/:room_id",
415//         1.1 => "/_matrix/client/v3/room_keys/keys/:room_id",
416//     }
417// };
418
419/// Request type for the `get_backup_keys_for_room` endpoint.
420#[derive(ToSchema, Deserialize, Debug)]
421pub struct AddKeysForRoomReqBody {
422    /// A map of session IDs to key data.
423    #[salvo(schema(value_type = Object, additional_properties = true))]
424    pub sessions: BTreeMap<OwnedSessionId, KeyBackupData>,
425}
426
427impl AddKeysForRoomReqBody {
428    /// Creates a new `Response` with the given sessions.
429    pub fn new(sessions: BTreeMap<OwnedSessionId, KeyBackupData>) -> Self {
430        Self { sessions }
431    }
432}
433
434/// `GET /_matrix/client/*/room_keys/keys/{room_id}/{sessionId}`
435///
436/// Retrieve a key from the backup for a given session.
437/// `/v3/` ([spec])
438///
439/// [spec]: https://spec.matrix.org/latest/client-server-api/#get_matrixclientv3room_keyskeysroomidsessionid
440
441// const METADATA: Metadata = metadata! {
442//     method: GET,
443//     rate_limited: true,
444//     authentication: AccessToken,
445//     history: {
446//         unstable => "/_matrix/client/unstable/room_keys/keys/:room_id/:session_id",
447//         1.0 => "/_matrix/client/r0/room_keys/keys/:room_id/:session_id",
448//         1.1 => "/_matrix/client/v3/room_keys/keys/:room_id/:session_id",
449//     }
450// };
451
452/// Request type for the `get_backup_keys_for_session` endpoint.
453
454#[derive(ToParameters, Deserialize, Debug)]
455pub struct KeysForSessionReqArgs {
456    /// The backup version to retrieve keys from.
457    #[salvo(parameter(parameter_in = Query))]
458    pub version: i64,
459
460    /// The ID of the room that the requested key is for.
461    #[salvo(parameter(parameter_in = Path))]
462    pub room_id: OwnedRoomId,
463
464    /// The ID of the megolm session whose key is requested.
465    #[salvo(parameter(parameter_in = Path))]
466    pub session_id: OwnedSessionId,
467}
468
469// /// Response type for the `get_backup_keys_for_session` endpoint.
470// #[derive(ToSchema, Serialize, Debug)]
471// pub struct KeysForSessionResBody (
472//     /// Information about the requested backup key.
473//     pub RawJson<KeyBackupData>,
474// );
475// impl KeysForSessionResBody {
476//     /// Creates a new `Response` with the given key_data.
477//     pub fn new(key_data: RawJson<KeyBackupData>) -> Self {
478//         Self (key_data)
479//     }
480// }
481
482/// `GET /_matrix/client/*/room_keys/keys`
483///
484/// Retrieve all keys from a backup version.
485/// `/v3/` ([spec])
486///
487/// [spec]: https://spec.matrix.org/latest/client-server-api/#get_matrixclientv3room_keyskeys
488
489// const METADATA: Metadata = metadata! {
490//     method: GET,
491//     rate_limited: true,
492//     authentication: AccessToken,
493//     history: {
494//         unstable => "/_matrix/client/unstable/room_keys/keys",
495//         1.0 => "/_matrix/client/r0/room_keys/keys",
496//         1.1 => "/_matrix/client/v3/room_keys/keys",
497//     }
498// };
499
500/// Request type for the `get_backup_keys` endpoint.
501
502// pub struct Requxest {
503//     /// The backup version to retrieve keys from.
504//     #[salvo(parameter(parameter_in = Query))]
505//     pub version: String,
506// }
507
508/// Response type for the `get_backup_keys` endpoint.
509
510#[derive(ToSchema, Serialize, Debug)]
511pub struct KeysResBody {
512    /// A map from room IDs to session IDs to key data.
513    pub rooms: BTreeMap<OwnedRoomId, RawJson<RoomKeyBackup>>,
514}
515impl KeysResBody {
516    /// Creates a new `Response` with the given room key backups.
517    pub fn new(rooms: BTreeMap<OwnedRoomId, RawJson<RoomKeyBackup>>) -> Self {
518        Self { rooms }
519    }
520}
521
522#[derive(ToSchema, Serialize, Debug)]
523pub struct KeysForRoomResBody {
524    /// A map from room IDs to session IDs to key data.
525    pub sessions: BTreeMap<OwnedRoomId, RawJson<RoomKeyBackup>>,
526}
527impl KeysForRoomResBody {
528    /// Creates a new `Response` with the given room key backups.
529    pub fn new(sessions: BTreeMap<OwnedRoomId, RawJson<RoomKeyBackup>>) -> Self {
530        Self { sessions }
531    }
532}
533
534/// `PUT /_matrix/client/*/room_keys/version/{version}`
535///
536/// Update information about an existing backup.
537/// `/v3/` ([spec])
538///
539/// [spec]: https://spec.matrix.org/latest/client-server-api/#put_matrixclientv3room_keysversionversion
540
541// const METADATA: Metadata = metadata! {
542//     method: PUT,
543//     rate_limited: true,
544//     authentication: AccessToken,
545//     history: {
546//         unstable => "/_matrix/client/unstable/room_keys/version/:version",
547//         1.1 => "/_matrix/client/v3/room_keys/version/:version",
548//     }
549// };
550
551/// Request type for the `update_backup_version` endpoint.
552#[derive(ToSchema, Deserialize, Debug)]
553pub struct UpdateVersionReqBody(
554    /// The algorithm used for storing backups.
555    pub BackupAlgorithm,
556);