#![allow(missing_docs)]
use std::collections::HashMap;
use http::Response;
use matrix_sdk_crypto::{
types::requests::{
AnyIncomingResponse, KeysBackupRequest, OutgoingRequest,
OutgoingVerificationRequest as SdkVerificationRequest, RoomMessageRequest, ToDeviceRequest,
UploadSigningKeysRequest as RustUploadSigningKeysRequest,
},
CrossSigningBootstrapRequests,
};
use ruma::{
api::client::{
backup::add_backup_keys::v3::Response as KeysBackupResponse,
keys::{
claim_keys::v3::{Request as KeysClaimRequest, Response as KeysClaimResponse},
get_keys::v3::Response as KeysQueryResponse,
upload_keys::v3::Response as KeysUploadResponse,
upload_signatures::v3::{
Request as RustSignatureUploadRequest, Response as SignatureUploadResponse,
},
},
message::send_message_event::v3::Response as RoomMessageResponse,
sync::sync_events::DeviceLists as RumaDeviceLists,
to_device::send_event_to_device::v3::Response as ToDeviceResponse,
},
assign,
events::EventContent,
OwnedTransactionId, UserId,
};
use serde_json::json;
#[derive(uniffi::Record)]
pub struct SignatureUploadRequest {
pub body: String,
}
impl From<RustSignatureUploadRequest> for SignatureUploadRequest {
fn from(r: RustSignatureUploadRequest) -> Self {
Self {
body: serde_json::to_string(&r.signed_keys)
.expect("Can't serialize signature upload request"),
}
}
}
#[derive(uniffi::Record)]
pub struct UploadSigningKeysRequest {
pub master_key: String,
pub self_signing_key: String,
pub user_signing_key: String,
}
impl From<RustUploadSigningKeysRequest> for UploadSigningKeysRequest {
fn from(r: RustUploadSigningKeysRequest) -> Self {
Self {
master_key: serde_json::to_string(
&r.master_key.expect("Request didn't contain a master key"),
)
.expect("Can't serialize cross signing master key"),
self_signing_key: serde_json::to_string(
&r.self_signing_key.expect("Request didn't contain a self-signing key"),
)
.expect("Can't serialize cross signing self-signing key"),
user_signing_key: serde_json::to_string(
&r.user_signing_key.expect("Request didn't contain a user-signing key"),
)
.expect("Can't serialize cross signing user-signing key"),
}
}
}
#[derive(uniffi::Record)]
pub struct BootstrapCrossSigningResult {
pub upload_keys_request: Option<Request>,
pub upload_signing_keys_request: UploadSigningKeysRequest,
pub upload_signature_request: SignatureUploadRequest,
}
impl From<CrossSigningBootstrapRequests> for BootstrapCrossSigningResult {
fn from(requests: CrossSigningBootstrapRequests) -> Self {
Self {
upload_signing_keys_request: requests.upload_signing_keys_req.into(),
upload_keys_request: requests.upload_keys_req.map(Request::from),
upload_signature_request: requests.upload_signatures_req.into(),
}
}
}
#[derive(uniffi::Enum)]
pub enum OutgoingVerificationRequest {
ToDevice { request_id: String, event_type: String, body: String },
InRoom { request_id: String, room_id: String, event_type: String, content: String },
}
impl From<SdkVerificationRequest> for OutgoingVerificationRequest {
fn from(r: SdkVerificationRequest) -> Self {
match r {
SdkVerificationRequest::ToDevice(r) => r.into(),
SdkVerificationRequest::InRoom(r) => Self::InRoom {
request_id: r.txn_id.to_string(),
room_id: r.room_id.to_string(),
content: serde_json::to_string(&r.content)
.expect("Can't serialize message content"),
event_type: r.content.event_type().to_string(),
},
}
}
}
impl From<ToDeviceRequest> for OutgoingVerificationRequest {
fn from(r: ToDeviceRequest) -> Self {
Self::ToDevice {
request_id: r.txn_id.to_string(),
event_type: r.event_type.to_string(),
body: serde_json::to_string(&r.messages).expect("Can't serialize to-device body"),
}
}
}
#[derive(Debug, uniffi::Enum)]
pub enum Request {
ToDevice { request_id: String, event_type: String, body: String },
KeysUpload { request_id: String, body: String },
KeysQuery { request_id: String, users: Vec<String> },
KeysClaim { request_id: String, one_time_keys: HashMap<String, HashMap<String, String>> },
KeysBackup { request_id: String, version: String, rooms: String },
RoomMessage { request_id: String, room_id: String, event_type: String, content: String },
SignatureUpload { request_id: String, body: String },
}
impl From<OutgoingRequest> for Request {
fn from(r: OutgoingRequest) -> Self {
use matrix_sdk_crypto::types::requests::AnyOutgoingRequest::*;
match r.request() {
KeysUpload(u) => {
let body = json!({
"device_keys": u.device_keys,
"one_time_keys": u.one_time_keys,
"fallback_keys": u.fallback_keys,
});
Request::KeysUpload {
request_id: r.request_id().to_string(),
body: serde_json::to_string(&body)
.expect("Can't serialize `/keys/upload` request"),
}
}
KeysQuery(k) => {
let users: Vec<String> = k.device_keys.keys().map(|u| u.to_string()).collect();
Request::KeysQuery { request_id: r.request_id().to_string(), users }
}
ToDeviceRequest(t) => Request::from(t),
SignatureUpload(t) => Request::SignatureUpload {
request_id: r.request_id().to_string(),
body: serde_json::to_string(&t.signed_keys)
.expect("Can't serialize signature upload request"),
},
RoomMessage(r) => Request::from(r),
KeysClaim(c) => (r.request_id().to_owned(), c.clone()).into(),
}
}
}
impl From<ToDeviceRequest> for Request {
fn from(r: ToDeviceRequest) -> Self {
Request::ToDevice {
request_id: r.txn_id.to_string(),
event_type: r.event_type.to_string(),
body: serde_json::to_string(&r.messages).expect("Can't serialize to-device body"),
}
}
}
impl From<(OwnedTransactionId, KeysClaimRequest)> for Request {
fn from(request_tuple: (OwnedTransactionId, KeysClaimRequest)) -> Self {
let (request_id, request) = request_tuple;
Request::KeysClaim {
request_id: request_id.to_string(),
one_time_keys: request
.one_time_keys
.into_iter()
.map(|(u, d)| {
(
u.to_string(),
d.into_iter().map(|(k, v)| (k.to_string(), v.to_string())).collect(),
)
})
.collect(),
}
}
}
impl From<(OwnedTransactionId, KeysBackupRequest)> for Request {
fn from(request_tuple: (OwnedTransactionId, KeysBackupRequest)) -> Self {
let (request_id, request) = request_tuple;
Request::KeysBackup {
request_id: request_id.to_string(),
version: request.version.to_owned(),
rooms: serde_json::to_string(&request.rooms)
.expect("Can't serialize keys backup request"),
}
}
}
impl From<&ToDeviceRequest> for Request {
fn from(r: &ToDeviceRequest) -> Self {
Request::ToDevice {
request_id: r.txn_id.to_string(),
event_type: r.event_type.to_string(),
body: serde_json::to_string(&r.messages).expect("Can't serialize to-device body"),
}
}
}
impl From<&RoomMessageRequest> for Request {
fn from(r: &RoomMessageRequest) -> Self {
Self::RoomMessage {
request_id: r.txn_id.to_string(),
room_id: r.room_id.to_string(),
event_type: r.content.event_type().to_string(),
content: serde_json::to_string(&r.content).expect("Can't serialize message content"),
}
}
}
pub(crate) fn response_from_string(body: &str) -> Response<Vec<u8>> {
Response::builder()
.status(200)
.body(body.as_bytes().to_vec())
.expect("Can't create HTTP response")
}
#[derive(uniffi::Enum)]
pub enum RequestType {
KeysQuery,
KeysClaim,
KeysUpload,
ToDevice,
SignatureUpload,
KeysBackup,
RoomMessage,
}
#[derive(uniffi::Record)]
pub struct DeviceLists {
pub changed: Vec<String>,
pub left: Vec<String>,
}
impl From<DeviceLists> for RumaDeviceLists {
fn from(d: DeviceLists) -> Self {
assign!(RumaDeviceLists::new(), {
changed: d
.changed
.into_iter()
.filter_map(|u| UserId::parse(u).ok())
.collect(),
left: d
.left
.into_iter()
.filter_map(|u| UserId::parse(u).ok())
.collect(),
})
}
}
#[derive(uniffi::Record)]
pub struct KeysImportResult {
pub imported: i64,
pub total: i64,
pub keys: HashMap<String, HashMap<String, Vec<String>>>,
}
pub(crate) enum OwnedResponse {
KeysClaim(KeysClaimResponse),
KeysUpload(KeysUploadResponse),
KeysQuery(KeysQueryResponse),
ToDevice(ToDeviceResponse),
SignatureUpload(SignatureUploadResponse),
KeysBackup(KeysBackupResponse),
RoomMessage(RoomMessageResponse),
}
impl From<KeysClaimResponse> for OwnedResponse {
fn from(response: KeysClaimResponse) -> Self {
OwnedResponse::KeysClaim(response)
}
}
impl From<KeysQueryResponse> for OwnedResponse {
fn from(response: KeysQueryResponse) -> Self {
OwnedResponse::KeysQuery(response)
}
}
impl From<KeysUploadResponse> for OwnedResponse {
fn from(response: KeysUploadResponse) -> Self {
OwnedResponse::KeysUpload(response)
}
}
impl From<ToDeviceResponse> for OwnedResponse {
fn from(response: ToDeviceResponse) -> Self {
OwnedResponse::ToDevice(response)
}
}
impl From<SignatureUploadResponse> for OwnedResponse {
fn from(response: SignatureUploadResponse) -> Self {
Self::SignatureUpload(response)
}
}
impl From<KeysBackupResponse> for OwnedResponse {
fn from(r: KeysBackupResponse) -> Self {
Self::KeysBackup(r)
}
}
impl From<RoomMessageResponse> for OwnedResponse {
fn from(response: RoomMessageResponse) -> Self {
OwnedResponse::RoomMessage(response)
}
}
impl<'a> From<&'a OwnedResponse> for AnyIncomingResponse<'a> {
fn from(r: &'a OwnedResponse) -> Self {
match r {
OwnedResponse::KeysClaim(r) => AnyIncomingResponse::KeysClaim(r),
OwnedResponse::KeysQuery(r) => AnyIncomingResponse::KeysQuery(r),
OwnedResponse::KeysUpload(r) => AnyIncomingResponse::KeysUpload(r),
OwnedResponse::ToDevice(r) => AnyIncomingResponse::ToDevice(r),
OwnedResponse::SignatureUpload(r) => AnyIncomingResponse::SignatureUpload(r),
OwnedResponse::KeysBackup(r) => AnyIncomingResponse::KeysBackup(r),
OwnedResponse::RoomMessage(r) => AnyIncomingResponse::RoomMessage(r),
}
}
}