| 1 | #![allow(missing_docs)] |
| 2 | |
| 3 | use std::collections::HashMap; |
| 4 | |
| 5 | use http::Response; |
| 6 | use matrix_sdk_crypto::{ |
| 7 | CrossSigningBootstrapRequests, |
| 8 | types::requests::{ |
| 9 | AnyIncomingResponse, KeysBackupRequest, OutgoingRequest, |
| 10 | OutgoingVerificationRequest as SdkVerificationRequest, RoomMessageRequest, ToDeviceRequest, |
| 11 | UploadSigningKeysRequest as RustUploadSigningKeysRequest, |
| 12 | }, |
| 13 | }; |
| 14 | use ruma::{ |
| 15 | OwnedTransactionId, UserId, |
| 16 | api::client::{ |
| 17 | backup::add_backup_keys::v3::Response as KeysBackupResponse, |
| 18 | keys::{ |
| 19 | claim_keys::v3::{Request as KeysClaimRequest, Response as KeysClaimResponse}, |
| 20 | get_keys::v3::Response as KeysQueryResponse, |
| 21 | upload_keys::v3::Response as KeysUploadResponse, |
| 22 | upload_signatures::v3::{ |
| 23 | Request as RustSignatureUploadRequest, Response as SignatureUploadResponse, |
| 24 | }, |
| 25 | }, |
| 26 | message::send_message_event::v3::Response as RoomMessageResponse, |
| 27 | sync::sync_events::DeviceLists as RumaDeviceLists, |
| 28 | to_device::send_event_to_device::v3::Response as ToDeviceResponse, |
| 29 | }, |
| 30 | assign, |
| 31 | events::MessageLikeEventContent, |
| 32 | }; |
| 33 | use serde_json::json; |
| 34 | |
| 35 | #[derive(uniffi::Record)] |
| 36 | pub struct SignatureUploadRequest { |
| 37 | pub body: String, |
| 38 | } |
| 39 | |
| 40 | impl From<RustSignatureUploadRequest> for SignatureUploadRequest { |
| 41 | fn from(r: RustSignatureUploadRequest) -> Self { |
| 42 | Self { |
| 43 | body: serde_json::to_string(&r.signed_keys) |
| 44 | .expect("Can't serialize signature upload request"), |
| 45 | } |
| 46 | } |
| 47 | } |
| 48 | |
| 49 | #[derive(uniffi::Record)] |
| 50 | pub struct UploadSigningKeysRequest { |
| 51 | pub master_key: String, |
| 52 | pub self_signing_key: String, |
| 53 | pub user_signing_key: String, |
| 54 | } |
| 55 | |
| 56 | impl From<RustUploadSigningKeysRequest> for UploadSigningKeysRequest { |
| 57 | fn from(r: RustUploadSigningKeysRequest) -> Self { |
| 58 | Self { |
| 59 | master_key: serde_json::to_string( |
| 60 | &r.master_key.expect("Request didn't contain a master key"), |
| 61 | ) |
| 62 | .expect("Can't serialize cross signing master key"), |
| 63 | self_signing_key: serde_json::to_string( |
| 64 | &r.self_signing_key.expect("Request didn't contain a self-signing key"), |
| 65 | ) |
| 66 | .expect("Can't serialize cross signing self-signing key"), |
| 67 | user_signing_key: serde_json::to_string( |
| 68 | &r.user_signing_key.expect("Request didn't contain a user-signing key"), |
| 69 | ) |
| 70 | .expect("Can't serialize cross signing user-signing key"), |
| 71 | } |
| 72 | } |
| 73 | } |
| 74 | |
| 75 | #[derive(uniffi::Record)] |
| 76 | pub struct BootstrapCrossSigningResult { |
| 77 | /// Optional request to upload some device keys alongside. |
| 78 | /// |
| 79 | /// Must be sent first if present, and marked with `mark_request_as_sent`. |
| 80 | pub upload_keys_request: Option<Request>, |
| 81 | /// Request to upload the signing keys. Must be sent second. |
| 82 | pub upload_signing_keys_request: UploadSigningKeysRequest, |
| 83 | /// Request to upload the keys signatures, including for the signing keys |
| 84 | /// and optionally for the device keys. Must be sent last. |
| 85 | pub upload_signature_request: SignatureUploadRequest, |
| 86 | } |
| 87 | |
| 88 | impl From<CrossSigningBootstrapRequests> for BootstrapCrossSigningResult { |
| 89 | fn from(requests: CrossSigningBootstrapRequests) -> Self { |
| 90 | Self { |
| 91 | upload_signing_keys_request: requests.upload_signing_keys_req.into(), |
| 92 | upload_keys_request: requests.upload_keys_req.map(Request::from), |
| 93 | upload_signature_request: requests.upload_signatures_req.into(), |
| 94 | } |
| 95 | } |
| 96 | } |
| 97 | |
| 98 | #[derive(uniffi::Enum)] |
| 99 | pub enum OutgoingVerificationRequest { |
| 100 | ToDevice { request_id: String, event_type: String, body: String }, |
| 101 | InRoom { request_id: String, room_id: String, event_type: String, content: String }, |
| 102 | } |
| 103 | |
| 104 | impl From<SdkVerificationRequest> for OutgoingVerificationRequest { |
| 105 | fn from(r: SdkVerificationRequest) -> Self { |
| 106 | match r { |
| 107 | SdkVerificationRequest::ToDevice(r) => r.into(), |
| 108 | SdkVerificationRequest::InRoom(r) => Self::InRoom { |
| 109 | request_id: r.txn_id.to_string(), |
| 110 | room_id: r.room_id.to_string(), |
| 111 | content: serde_json::to_string(&r.content) |
| 112 | .expect("Can't serialize message content"), |
| 113 | event_type: r.content.event_type().to_string(), |
| 114 | }, |
| 115 | } |
| 116 | } |
| 117 | } |
| 118 | |
| 119 | impl From<ToDeviceRequest> for OutgoingVerificationRequest { |
| 120 | fn from(r: ToDeviceRequest) -> Self { |
| 121 | Self::ToDevice { |
| 122 | request_id: r.txn_id.to_string(), |
| 123 | event_type: r.event_type.to_string(), |
| 124 | body: serde_json::to_string(&r.messages).expect("Can't serialize to-device body"), |
| 125 | } |
| 126 | } |
| 127 | } |
| 128 | |
| 129 | #[derive(Debug, uniffi::Enum)] |
| 130 | pub enum Request { |
| 131 | ToDevice { request_id: String, event_type: String, body: String }, |
| 132 | KeysUpload { request_id: String, body: String }, |
| 133 | KeysQuery { request_id: String, users: Vec<String> }, |
| 134 | KeysClaim { request_id: String, one_time_keys: HashMap<String, HashMap<String, String>> }, |
| 135 | KeysBackup { request_id: String, version: String, rooms: String }, |
| 136 | RoomMessage { request_id: String, room_id: String, event_type: String, content: String }, |
| 137 | SignatureUpload { request_id: String, body: String }, |
| 138 | } |
| 139 | |
| 140 | impl From<OutgoingRequest> for Request { |
| 141 | fn from(r: OutgoingRequest) -> Self { |
| 142 | use matrix_sdk_crypto::types::requests::AnyOutgoingRequest::*; |
| 143 | |
| 144 | match r.request() { |
| 145 | KeysUpload(u) => { |
| 146 | let body = json!({ |
| 147 | "device_keys": u.device_keys, |
| 148 | "one_time_keys": u.one_time_keys, |
| 149 | "fallback_keys": u.fallback_keys, |
| 150 | }); |
| 151 | |
| 152 | Request::KeysUpload { |
| 153 | request_id: r.request_id().to_string(), |
| 154 | body: serde_json::to_string(&body) |
| 155 | .expect("Can't serialize `/keys/upload` request"), |
| 156 | } |
| 157 | } |
| 158 | KeysQuery(k) => { |
| 159 | let users: Vec<String> = k.device_keys.keys().map(|u| u.to_string()).collect(); |
| 160 | Request::KeysQuery { request_id: r.request_id().to_string(), users } |
| 161 | } |
| 162 | ToDeviceRequest(t) => Request::from(t), |
| 163 | SignatureUpload(t) => Request::SignatureUpload { |
| 164 | request_id: r.request_id().to_string(), |
| 165 | body: serde_json::to_string(&t.signed_keys) |
| 166 | .expect("Can't serialize signature upload request"), |
| 167 | }, |
| 168 | RoomMessage(r) => Request::from(r), |
| 169 | KeysClaim(c) => (r.request_id().to_owned(), c.clone()).into(), |
| 170 | } |
| 171 | } |
| 172 | } |
| 173 | |
| 174 | impl From<ToDeviceRequest> for Request { |
| 175 | fn from(r: ToDeviceRequest) -> Self { |
| 176 | Request::ToDevice { |
| 177 | request_id: r.txn_id.to_string(), |
| 178 | event_type: r.event_type.to_string(), |
| 179 | body: serde_json::to_string(&r.messages).expect("Can't serialize to-device body"), |
| 180 | } |
| 181 | } |
| 182 | } |
| 183 | |
| 184 | impl From<(OwnedTransactionId, KeysClaimRequest)> for Request { |
| 185 | fn from(request_tuple: (OwnedTransactionId, KeysClaimRequest)) -> Self { |
| 186 | let (request_id, request) = request_tuple; |
| 187 | |
| 188 | Request::KeysClaim { |
| 189 | request_id: request_id.to_string(), |
| 190 | one_time_keys: request |
| 191 | .one_time_keys |
| 192 | .into_iter() |
| 193 | .map(|(u, d)| { |
| 194 | ( |
| 195 | u.to_string(), |
| 196 | d.into_iter().map(|(k, v)| (k.to_string(), v.to_string())).collect(), |
| 197 | ) |
| 198 | }) |
| 199 | .collect(), |
| 200 | } |
| 201 | } |
| 202 | } |
| 203 | |
| 204 | impl From<(OwnedTransactionId, KeysBackupRequest)> for Request { |
| 205 | fn from(request_tuple: (OwnedTransactionId, KeysBackupRequest)) -> Self { |
| 206 | let (request_id, request) = request_tuple; |
| 207 | |
| 208 | Request::KeysBackup { |
| 209 | request_id: request_id.to_string(), |
| 210 | version: request.version.to_owned(), |
| 211 | rooms: serde_json::to_string(&request.rooms) |
| 212 | .expect("Can't serialize keys backup request"), |
| 213 | } |
| 214 | } |
| 215 | } |
| 216 | |
| 217 | impl From<&ToDeviceRequest> for Request { |
| 218 | fn from(r: &ToDeviceRequest) -> Self { |
| 219 | Request::ToDevice { |
| 220 | request_id: r.txn_id.to_string(), |
| 221 | event_type: r.event_type.to_string(), |
| 222 | body: serde_json::to_string(&r.messages).expect("Can't serialize to-device body"), |
| 223 | } |
| 224 | } |
| 225 | } |
| 226 | |
| 227 | impl From<&Box<RoomMessageRequest>> for Request { |
| 228 | fn from(r: &Box<RoomMessageRequest>) -> Self { |
| 229 | Self::RoomMessage { |
| 230 | request_id: r.txn_id.to_string(), |
| 231 | room_id: r.room_id.to_string(), |
| 232 | event_type: r.content.event_type().to_string(), |
| 233 | content: serde_json::to_string(&r.content).expect("Can't serialize message content"), |
| 234 | } |
| 235 | } |
| 236 | } |
| 237 | |
| 238 | pub(crate) fn response_from_string(body: &str) -> Response<Vec<u8>> { |
| 239 | Response::builder() |
| 240 | .status(200) |
| 241 | .body(body.as_bytes().to_vec()) |
| 242 | .expect("Can't create HTTP response") |
| 243 | } |
| 244 | |
| 245 | #[derive(uniffi::Enum)] |
| 246 | pub enum RequestType { |
| 247 | KeysQuery, |
| 248 | KeysClaim, |
| 249 | KeysUpload, |
| 250 | ToDevice, |
| 251 | SignatureUpload, |
| 252 | KeysBackup, |
| 253 | RoomMessage, |
| 254 | } |
| 255 | |
| 256 | #[derive(uniffi::Record)] |
| 257 | pub struct DeviceLists { |
| 258 | pub changed: Vec<String>, |
| 259 | pub left: Vec<String>, |
| 260 | } |
| 261 | |
| 262 | impl From<DeviceLists> for RumaDeviceLists { |
| 263 | fn from(d: DeviceLists) -> Self { |
| 264 | assign!(RumaDeviceLists::new(), { |
| 265 | changed: d |
| 266 | .changed |
| 267 | .into_iter() |
| 268 | .filter_map(|u| UserId::parse(u).ok()) |
| 269 | .collect(), |
| 270 | left: d |
| 271 | .left |
| 272 | .into_iter() |
| 273 | .filter_map(|u| UserId::parse(u).ok()) |
| 274 | .collect(), |
| 275 | }) |
| 276 | } |
| 277 | } |
| 278 | |
| 279 | #[derive(uniffi::Record)] |
| 280 | pub struct KeysImportResult { |
| 281 | /// The number of room keys that were imported. |
| 282 | pub imported: i64, |
| 283 | /// The total number of room keys that were found in the export. |
| 284 | pub total: i64, |
| 285 | /// The map of keys that were imported. |
| 286 | /// |
| 287 | /// It's a map from room id to a map of the sender key to a list of session |
| 288 | /// ids. |
| 289 | pub keys: HashMap<String, HashMap<String, Vec<String>>>, |
| 290 | } |
| 291 | |
| 292 | pub(crate) enum OwnedResponse { |
| 293 | KeysClaim(KeysClaimResponse), |
| 294 | KeysUpload(KeysUploadResponse), |
| 295 | KeysQuery(KeysQueryResponse), |
| 296 | ToDevice(ToDeviceResponse), |
| 297 | SignatureUpload(SignatureUploadResponse), |
| 298 | KeysBackup(KeysBackupResponse), |
| 299 | RoomMessage(RoomMessageResponse), |
| 300 | } |
| 301 | |
| 302 | impl From<KeysClaimResponse> for OwnedResponse { |
| 303 | fn from(response: KeysClaimResponse) -> Self { |
| 304 | OwnedResponse::KeysClaim(response) |
| 305 | } |
| 306 | } |
| 307 | |
| 308 | impl From<KeysQueryResponse> for OwnedResponse { |
| 309 | fn from(response: KeysQueryResponse) -> Self { |
| 310 | OwnedResponse::KeysQuery(response) |
| 311 | } |
| 312 | } |
| 313 | |
| 314 | impl From<KeysUploadResponse> for OwnedResponse { |
| 315 | fn from(response: KeysUploadResponse) -> Self { |
| 316 | OwnedResponse::KeysUpload(response) |
| 317 | } |
| 318 | } |
| 319 | |
| 320 | impl From<ToDeviceResponse> for OwnedResponse { |
| 321 | fn from(response: ToDeviceResponse) -> Self { |
| 322 | OwnedResponse::ToDevice(response) |
| 323 | } |
| 324 | } |
| 325 | |
| 326 | impl From<SignatureUploadResponse> for OwnedResponse { |
| 327 | fn from(response: SignatureUploadResponse) -> Self { |
| 328 | Self::SignatureUpload(response) |
| 329 | } |
| 330 | } |
| 331 | |
| 332 | impl From<KeysBackupResponse> for OwnedResponse { |
| 333 | fn from(r: KeysBackupResponse) -> Self { |
| 334 | Self::KeysBackup(r) |
| 335 | } |
| 336 | } |
| 337 | |
| 338 | impl From<RoomMessageResponse> for OwnedResponse { |
| 339 | fn from(response: RoomMessageResponse) -> Self { |
| 340 | OwnedResponse::RoomMessage(response) |
| 341 | } |
| 342 | } |
| 343 | |
| 344 | impl<'a> From<&'a OwnedResponse> for AnyIncomingResponse<'a> { |
| 345 | fn from(r: &'a OwnedResponse) -> Self { |
| 346 | match r { |
| 347 | OwnedResponse::KeysClaim(r) => AnyIncomingResponse::KeysClaim(r), |
| 348 | OwnedResponse::KeysQuery(r) => AnyIncomingResponse::KeysQuery(r), |
| 349 | OwnedResponse::KeysUpload(r) => AnyIncomingResponse::KeysUpload(r), |
| 350 | OwnedResponse::ToDevice(r) => AnyIncomingResponse::ToDevice(r), |
| 351 | OwnedResponse::SignatureUpload(r) => AnyIncomingResponse::SignatureUpload(r), |
| 352 | OwnedResponse::KeysBackup(r) => AnyIncomingResponse::KeysBackup(r), |
| 353 | OwnedResponse::RoomMessage(r) => AnyIncomingResponse::RoomMessage(r), |
| 354 | } |
| 355 | } |
| 356 | } |