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);