Merge branch 'master' into crypto-improvements

master
Damir Jelić 2020-10-13 13:02:02 +02:00
commit 3338ecf62a
14 changed files with 135 additions and 83 deletions

View File

@ -28,14 +28,15 @@ socks = ["reqwest/socks"]
docs = ["encryption", "sqlite_cryptostore", "messages"] docs = ["encryption", "sqlite_cryptostore", "messages"]
[dependencies] [dependencies]
async-trait = "0.1.40" async-trait = "0.1.41"
dashmap = { version = "3.11.10", optional = true } dashmap = { version = "3.11.10", optional = true }
http = "0.2.1" http = "0.2.1"
serde_json = "1.0.57" serde_json = "1.0.58"
thiserror = "1.0.20" thiserror = "1.0.21"
tracing = "0.1.19" tracing = "0.1.21"
url = "2.1.1" url = "2.1.1"
zeroize = "1.1.0" zeroize = "1.1.1"
mime = "0.3.16"
matrix-sdk-common-macros = { version = "0.1.0", path = "../matrix_sdk_common_macros" } matrix-sdk-common-macros = { version = "0.1.0", path = "../matrix_sdk_common_macros" }
matrix-sdk-common = { version = "0.1.0", path = "../matrix_sdk_common" } matrix-sdk-common = { version = "0.1.0", path = "../matrix_sdk_common" }
@ -67,17 +68,17 @@ version = "3.0.2"
features = ["wasm-bindgen"] features = ["wasm-bindgen"]
[dev-dependencies] [dev-dependencies]
async-trait = "0.1.40" async-trait = "0.1.41"
async-std = { version = "1.6.5", features = ["unstable"] } async-std = { version = "1.6.5", features = ["unstable"] }
dirs = "3.0.1" dirs = "3.0.1"
matrix-sdk-test = { version = "0.1.0", path = "../matrix_sdk_test" } matrix-sdk-test = { version = "0.1.0", path = "../matrix_sdk_test" }
tokio = { version = "0.2.22", features = ["rt-threaded", "macros"] } tokio = { version = "0.2.22", features = ["rt-threaded", "macros"] }
serde_json = "1.0.57" serde_json = "1.0.58"
tracing-subscriber = "0.2.11" tracing-subscriber = "0.2.13"
tempfile = "3.1.0" tempfile = "3.1.0"
mockito = "0.27.0" mockito = "0.27.0"
lazy_static = "1.4.0" lazy_static = "1.4.0"
futures = "0.3.5" futures = "0.3.6"
[[example]] [[example]]
name = "emoji_verification" name = "emoji_verification"

View File

@ -1,4 +1,5 @@
use std::{env, process::exit}; use std::{env, process::exit};
use tokio::time::{delay_for, Duration};
use matrix_sdk::{ use matrix_sdk::{
self, self,
@ -32,11 +33,27 @@ impl EventEmitter for AutoJoinBot {
if let SyncRoom::Invited(room) = room { if let SyncRoom::Invited(room) = room {
let room = room.read().await; let room = room.read().await;
println!("Autojoining room {}", room.display_name()); println!("Autojoining room {}", room.room_id);
self.client let mut delay = 2;
.join_room_by_id(&room.room_id)
.await while let Err(err) = self.client.join_room_by_id(&room.room_id).await {
.expect("Can't join room"); // retry autojoin due to synapse sending invites, before the
// invited user can join for more information see
// https://github.com/matrix-org/synapse/issues/4345
eprintln!(
"Failed to join room {} ({:?}), retrying in {}s",
room.room_id, err, delay
);
delay_for(Duration::from_secs(delay)).await;
delay *= 2;
if delay > 3600 {
eprintln!("Can't join room {} ({:?})", room.room_id, err);
break;
}
}
println!("Successfully joined room {}", room.room_id);
} }
} }
} }

View File

@ -52,7 +52,7 @@ impl EventEmitter for ImageBot {
let mut image = self.image.lock().await; let mut image = self.image.lock().await;
self.client self.client
.room_send_attachment(&room_id, "cat", "image/jpg", &mut *image, None) .room_send_attachment(&room_id, "cat", &mime::IMAGE_JPEG, &mut *image, None)
.await .await
.unwrap(); .unwrap();

View File

@ -30,6 +30,7 @@ use std::{
use dashmap::DashMap; use dashmap::DashMap;
use futures_timer::Delay as sleep; use futures_timer::Delay as sleep;
use http::HeaderValue; use http::HeaderValue;
use mime::{self, Mime};
use reqwest::header::InvalidHeaderValue; use reqwest::header::InvalidHeaderValue;
use url::Url; use url::Url;
#[cfg(feature = "encryption")] #[cfg(feature = "encryption")]
@ -871,12 +872,9 @@ impl Client {
self.send(request).await self.send(request).await
} }
/// Get messages starting at a specific sync point using the /// Sends a request to `/_matrix/client/r0/rooms/{room_id}/messages` and returns
/// `MessagesRequestBuilder`s `from` field as a starting point. /// a `get_message_events::Response` that contains a chunk of room and state events
/// /// (`AnyRoomEvent` and `AnyStateEvent`).
/// Sends a request to `/_matrix/client/r0/rooms/{room_id}/messages` and
/// returns a `get_message_events::Response` that contains chunks
/// of `RoomEvents`.
/// ///
/// # Arguments /// # Arguments
/// ///
@ -1162,6 +1160,7 @@ impl Client {
/// # use std::{path::PathBuf, fs::File, io::Read}; /// # use std::{path::PathBuf, fs::File, io::Read};
/// # use matrix_sdk::{Client, identifiers::room_id}; /// # use matrix_sdk::{Client, identifiers::room_id};
/// # use url::Url; /// # use url::Url;
/// # use mime;
/// # use futures::executor::block_on; /// # use futures::executor::block_on;
/// # block_on(async { /// # block_on(async {
/// # let homeserver = Url::parse("http://localhost:8080").unwrap(); /// # let homeserver = Url::parse("http://localhost:8080").unwrap();
@ -1171,7 +1170,7 @@ impl Client {
/// let mut image = File::open(path).unwrap(); /// let mut image = File::open(path).unwrap();
/// ///
/// let response = client /// let response = client
/// .room_send_attachment(&room_id, "My favorite cat", "image/jpg", &mut image, None) /// .room_send_attachment(&room_id, "My favorite cat", &mime::IMAGE_JPEG, &mut image, None)
/// .await /// .await
/// .expect("Can't upload my cat."); /// .expect("Can't upload my cat.");
/// # }); /// # });
@ -1180,7 +1179,7 @@ impl Client {
&self, &self,
room_id: &RoomId, room_id: &RoomId,
body: &str, body: &str,
content_type: &str, content_type: &Mime,
mut reader: &mut R, mut reader: &mut R,
txn_id: Option<Uuid>, txn_id: Option<Uuid>,
) -> Result<send_message_event::Response> { ) -> Result<send_message_event::Response> {
@ -1188,9 +1187,9 @@ impl Client {
#[cfg(feature = "encryption")] #[cfg(feature = "encryption")]
let mut reader = AttachmentEncryptor::new(reader); let mut reader = AttachmentEncryptor::new(reader);
#[cfg(feature = "encryption")] #[cfg(feature = "encryption")]
let content_type = "application/octet-stream"; let content_type = mime::APPLICATION_OCTET_STREAM;
let response = self.upload(content_type, &mut reader).await?; let response = self.upload(&content_type, &mut reader).await?;
#[cfg(feature = "encryption")] #[cfg(feature = "encryption")]
let keys = { let keys = {
@ -1208,13 +1207,14 @@ impl Client {
(response, keys) (response, keys)
} else { } else {
let response = self.upload(content_type, &mut reader).await?; let response = self.upload(&content_type, &mut reader).await?;
(response, None) (response, None)
}; };
let url = response.content_uri; let url = response.content_uri;
let content = if content_type.starts_with("image") { let content = match content_type.type_() {
mime::IMAGE => {
// TODO create a thumbnail using the image crate?. // TODO create a thumbnail using the image crate?.
MessageEventContent::Image(ImageMessageEventContent { MessageEventContent::Image(ImageMessageEventContent {
body: body.to_owned(), body: body.to_owned(),
@ -1222,28 +1222,26 @@ impl Client {
url: Some(url), url: Some(url),
file: encrypted_file, file: encrypted_file,
}) })
} else if content_type.starts_with("audio") { }
MessageEventContent::Audio(AudioMessageEventContent { mime::AUDIO => MessageEventContent::Audio(AudioMessageEventContent {
body: body.to_owned(), body: body.to_owned(),
info: None, info: None,
url: Some(url), url: Some(url),
file: encrypted_file, file: encrypted_file,
}) }),
} else if content_type.starts_with("video") { mime::VIDEO => MessageEventContent::Video(VideoMessageEventContent {
MessageEventContent::Video(VideoMessageEventContent {
body: body.to_owned(), body: body.to_owned(),
info: None, info: None,
url: Some(url), url: Some(url),
file: encrypted_file, file: encrypted_file,
}) }),
} else { _ => MessageEventContent::File(FileMessageEventContent {
MessageEventContent::File(FileMessageEventContent {
filename: None, filename: None,
body: body.to_owned(), body: body.to_owned(),
info: None, info: None,
url: Some(url), url: Some(url),
file: encrypted_file, file: encrypted_file,
}) }),
}; };
self.room_send( self.room_send(
@ -1271,6 +1269,7 @@ impl Client {
/// # use matrix_sdk::{Client, identifiers::room_id}; /// # use matrix_sdk::{Client, identifiers::room_id};
/// # use url::Url; /// # use url::Url;
/// # use futures::executor::block_on; /// # use futures::executor::block_on;
/// # use mime;
/// # block_on(async { /// # block_on(async {
/// # let homeserver = Url::parse("http://localhost:8080").unwrap(); /// # let homeserver = Url::parse("http://localhost:8080").unwrap();
/// # let mut client = Client::new(homeserver).unwrap(); /// # let mut client = Client::new(homeserver).unwrap();
@ -1278,7 +1277,7 @@ impl Client {
/// let mut image = File::open(path).unwrap(); /// let mut image = File::open(path).unwrap();
/// ///
/// let response = client /// let response = client
/// .upload("image/jpg", &mut image) /// .upload(&mime::IMAGE_JPEG, &mut image)
/// .await /// .await
/// .expect("Can't upload my cat."); /// .expect("Can't upload my cat.");
/// ///
@ -1287,13 +1286,13 @@ impl Client {
/// ``` /// ```
pub async fn upload( pub async fn upload(
&self, &self,
content_type: &str, content_type: &Mime,
reader: &mut impl Read, reader: &mut impl Read,
) -> Result<create_content::Response> { ) -> Result<create_content::Response> {
let mut data = Vec::new(); let mut data = Vec::new();
reader.read_to_end(&mut data)?; reader.read_to_end(&mut data)?;
let request = create_content::Request::new(content_type, data); let request = create_content::Request::new(content_type.essence_str(), data);
self.http_client.upload(request).await self.http_client.upload(request).await
} }
@ -2524,7 +2523,7 @@ mod test {
Matcher::Regex(r"^/_matrix/media/r0/upload".to_string()), Matcher::Regex(r"^/_matrix/media/r0/upload".to_string()),
) )
.with_status(200) .with_status(200)
.match_header("content-type", "image/jpg") .match_header("content-type", "image/jpeg")
.with_body( .with_body(
json!({ json!({
"content_uri": "mxc://example.com/AQwafuaFswefuhsfAFAgsw" "content_uri": "mxc://example.com/AQwafuaFswefuhsfAFAgsw"
@ -2538,7 +2537,7 @@ mod test {
let mut media = Cursor::new("Hello world"); let mut media = Cursor::new("Hello world");
let response = client let response = client
.room_send_attachment(&room_id, "image", "image/jpg", &mut media, None) .room_send_attachment(&room_id, "image", &mime::IMAGE_JPEG, &mut media, None)
.await .await
.unwrap(); .unwrap();

View File

@ -15,7 +15,24 @@
//! This crate implements a [Matrix](https://matrix.org/) client library. //! This crate implements a [Matrix](https://matrix.org/) client library.
//! //!
//! ## Crate Feature Flags //! # Enabling logging
//!
//! Users of the matrix-sdk crate can enable log output by depending on the `tracing-subscriber`
//! crate and including the following line in their application (e.g. at the start of `main`):
//!
//! ```rust
//! tracing_subscriber::fmt::init();
//! ```
//!
//! The log output is controlled via the `RUST_LOG` environment variable by setting it to one of
//! the `error`, `warn`, `info`, `debug` or `trace` levels. The output is printed to stdout.
//!
//! The `RUST_LOG` variable also supports a more advanced syntax for filtering log output more
//! precisely, for instance with crate-level granularity. For more information on this, check out
//! the [tracing_subscriber
//! documentation](https://tracing.rs/tracing_subscriber/filter/struct.envfilter).
//!
//! # Crate Feature Flags
//! //!
//! The following crate feature flags are available: //! The following crate feature flags are available:
//! //!

View File

@ -24,18 +24,18 @@ unstable-synapse-quirks = ["matrix-sdk-common/unstable-synapse-quirks"]
docs = ["encryption", "sqlite_cryptostore", "messages"] docs = ["encryption", "sqlite_cryptostore", "messages"]
[dependencies] [dependencies]
async-trait = "0.1.40" async-trait = "0.1.41"
serde = "1.0.115" serde = "1.0.116"
serde_json = "1.0.57" serde_json = "1.0.58"
zeroize = "1.1.0" zeroize = "1.1.1"
tracing = "0.1.19" tracing = "0.1.21"
matrix-sdk-common-macros = { version = "0.1.0", path = "../matrix_sdk_common_macros" } matrix-sdk-common-macros = { version = "0.1.0", path = "../matrix_sdk_common_macros" }
matrix-sdk-common = { version = "0.1.0", path = "../matrix_sdk_common" } matrix-sdk-common = { version = "0.1.0", path = "../matrix_sdk_common" }
matrix-sdk-crypto = { version = "0.1.0", path = "../matrix_sdk_crypto", optional = true } matrix-sdk-crypto = { version = "0.1.0", path = "../matrix_sdk_crypto", optional = true }
# Misc dependencies # Misc dependencies
thiserror = "1.0.20" thiserror = "1.0.21"
[target.'cfg(not(target_arch = "wasm32"))'.dependencies.tokio] [target.'cfg(not(target_arch = "wasm32"))'.dependencies.tokio]
version = "0.2.22" version = "0.2.22"
@ -43,10 +43,10 @@ default-features = false
features = ["sync", "fs"] features = ["sync", "fs"]
[dev-dependencies] [dev-dependencies]
futures = "0.3.5" futures = "0.3.6"
matrix-sdk-test = { version = "0.1.0", path = "../matrix_sdk_test" } matrix-sdk-test = { version = "0.1.0", path = "../matrix_sdk_test" }
http = "0.2.1" http = "0.2.1"
tracing-subscriber = "0.2.11" tracing-subscriber = "0.2.13"
tempfile = "3.1.0" tempfile = "3.1.0"
mockito = "0.27.0" mockito = "0.27.0"
@ -54,4 +54,4 @@ mockito = "0.27.0"
tokio = { version = "0.2.22", features = ["rt-threaded", "macros"] } tokio = { version = "0.2.22", features = ["rt-threaded", "macros"] }
[target.'cfg(target_arch = "wasm32")'.dev-dependencies] [target.'cfg(target_arch = "wasm32")'.dev-dependencies]
wasm-bindgen-test = "0.3.17" wasm-bindgen-test = "0.3.18"

View File

@ -1886,6 +1886,16 @@ impl BaseClient {
} }
} }
/// Get the user login session.
///
/// If the client is currently logged in, this will return a `matrix_sdk::Session` object which
/// can later be given to `restore_login`.
///
/// Returns a session object if the client is logged in. Otherwise returns `None`.
pub async fn get_session(&self) -> Option<Session> {
self.session.read().await.clone()
}
/// Get a map holding all the devices of an user. /// Get a map holding all the devices of an user.
/// ///
/// This will always return an empty map if the client hasn't been logged /// This will always return an empty map if the client hasn't been logged

View File

@ -647,7 +647,7 @@ impl Room {
if state_event && !self.member_is_tracked(&target_user) { if state_event && !self.member_is_tracked(&target_user) {
debug!( debug!(
"handle_membership: User {user_id} is {state} the room {room_id} ({room_name})", "handle_membership: User {user_id} {state} the room {room_id} ({room_name})",
user_id = target_user, user_id = target_user,
state = event.content.membership.describe(), state = event.content.membership.describe(),
room_id = self.room_id, room_id = self.room_id,
@ -1089,8 +1089,8 @@ impl Describe for MembershipState {
Self::Ban => "is banned in", Self::Ban => "is banned in",
Self::Invite => "is invited to", Self::Invite => "is invited to",
Self::Join => "is a member of", Self::Join => "is a member of",
Self::Knock => "is requesting access", Self::Knock => "is requesting access to",
Self::Leave => "left", Self::Leave => "has left",
} }
.to_string() .to_string()
} }
@ -1112,12 +1112,12 @@ impl Describe for MembershipChange {
displayname_changed, displayname_changed,
avatar_url_changed, avatar_url_changed,
} => match (*displayname_changed, *avatar_url_changed) { } => match (*displayname_changed, *avatar_url_changed) {
(true, true) => "changed their displayname and avatar", (true, true) => "changed their displayname and avatar in",
(true, false) => "changed their displayname", (true, false) => "changed their displayname in",
(false, true) => "changed their avatar", (false, true) => "changed their avatar in",
_ => { _ => {
error!("Got ProfileChanged but nothing changed"); error!("Got ProfileChanged but nothing changed");
"impossible: changed nothing in their profile" "impossible: changed nothing in their profile in"
} }
}, },
Self::None => "did nothing in", Self::None => "did nothing in",

View File

@ -15,11 +15,13 @@
//! User sessions. //! User sessions.
use serde::{Deserialize, Serialize};
use matrix_sdk_common::identifiers::{DeviceId, UserId}; use matrix_sdk_common::identifiers::{DeviceId, UserId};
/// A user session, containing an access token and information about the /// A user session, containing an access token and information about the
/// associated user account. /// associated user account.
#[derive(Clone, Debug, Eq, Hash, PartialEq)] #[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)]
pub struct Session { pub struct Session {
/// The access token used for this session. /// The access token used for this session.
pub access_token: String, pub access_token: String,

View File

@ -15,7 +15,7 @@ unstable-synapse-quirks = ["ruma/unstable-synapse-quirks"]
[dependencies] [dependencies]
assign = "1.1.0" assign = "1.1.0"
instant = { version = "0.1.6", features = ["wasm-bindgen", "now"] } instant = { version = "0.1.7", features = ["wasm-bindgen", "now"] }
js_int = "0.1.9" js_int = "0.1.9"
[dependencies.ruma] [dependencies.ruma]

View File

@ -14,5 +14,5 @@ version = "0.1.0"
proc-macro = true proc-macro = true
[dependencies] [dependencies]
syn = "1.0.40" syn = "1.0.44"
quote = "1.0.7" quote = "1.0.7"

View File

@ -20,29 +20,29 @@ sqlite_cryptostore = ["sqlx"]
docs = ["sqlite_cryptostore"] docs = ["sqlite_cryptostore"]
[dependencies] [dependencies]
async-trait = "0.1.40" async-trait = "0.1.41"
matrix-sdk-common-macros = { version = "0.1.0", path = "../matrix_sdk_common_macros" } matrix-sdk-common-macros = { version = "0.1.0", path = "../matrix_sdk_common_macros" }
matrix-sdk-common = { version = "0.1.0", path = "../matrix_sdk_common" } matrix-sdk-common = { version = "0.1.0", path = "../matrix_sdk_common" }
olm-rs = { version = "0.6.0", features = ["serde"] } olm-rs = { version = "1.0.0", features = ["serde"] }
getrandom = "0.2.0" getrandom = "0.2.0"
serde = { version = "1.0.115", features = ["derive", "rc"] } serde = { version = "1.0.116", features = ["derive", "rc"] }
serde_json = "1.0.57" serde_json = "1.0.58"
cjson = "0.1.1" cjson = "0.1.1"
zeroize = { version = "1.1.0", features = ["zeroize_derive"] } zeroize = { version = "1.1.1", features = ["zeroize_derive"] }
url = "2.1.1" url = "2.1.1"
# Misc dependencies # Misc dependencies
thiserror = "1.0.20" thiserror = "1.0.21"
tracing = "0.1.19" tracing = "0.1.21"
atomic = "0.5.0" atomic = "0.5.0"
dashmap = "3.11.10" dashmap = "3.11.10"
sha2 = "0.9.1" sha2 = "0.9.1"
aes-ctr = "0.4.0" aes-ctr = "0.5.0"
pbkdf2 = { version = "0.5.0", default-features = false } pbkdf2 = { version = "0.5.0", default-features = false }
hmac = "0.9.0" hmac = "0.9.0"
base64 = "0.12.3" base64 = "0.13.0"
byteorder = "1.3.4" byteorder = "1.3.4"
[dependencies.tracing-futures] [dependencies.tracing-futures]
@ -58,10 +58,10 @@ features = ["runtime-tokio", "sqlite", "macros"]
[dev-dependencies] [dev-dependencies]
tokio = { version = "0.2.22", features = ["rt-threaded", "macros"] } tokio = { version = "0.2.22", features = ["rt-threaded", "macros"] }
futures = "0.3.5" futures = "0.3.6"
proptest = "0.10.1" proptest = "0.10.1"
serde_json = "1.0.57" serde_json = "1.0.58"
tempfile = "3.1.0" tempfile = "3.1.0"
http = "0.2.1" http = "0.2.1"
matrix-sdk-test = { version = "0.1.0", path = "../matrix_sdk_test" } matrix-sdk-test = { version = "0.1.0", path = "../matrix_sdk_test" }
indoc = "1.0.2" indoc = "1.0.3"

View File

@ -1219,7 +1219,8 @@ impl CryptoStore for SqliteStore {
) VALUES (?1, ?2, ?3, ?4, ?5) ) VALUES (?1, ?2, ?3, ?4, ?5)
ON CONFLICT(user_id, device_id) DO UPDATE SET ON CONFLICT(user_id, device_id) DO UPDATE SET
pickle = excluded.pickle, pickle = excluded.pickle,
shared = excluded.shared shared = excluded.shared,
uploaded_key_count = excluded.uploaded_key_count
", ",
) )
.bind(pickle.user_id.as_str()) .bind(pickle.user_id.as_str())
@ -1612,6 +1613,7 @@ mod test {
.expect("Can't save account"); .expect("Can't save account");
account.mark_as_shared(); account.mark_as_shared();
account.update_uploaded_key_count(50);
store store
.save_account(account.clone()) .save_account(account.clone())
@ -1622,6 +1624,10 @@ mod test {
let loaded_account = loaded_account.unwrap(); let loaded_account = loaded_account.unwrap();
assert_eq!(account, loaded_account); assert_eq!(account, loaded_account);
assert_eq!(
account.uploaded_key_count(),
loaded_account.uploaded_key_count()
);
} }
#[tokio::test] #[tokio::test]

View File

@ -11,9 +11,9 @@ repository = "https://github.com/matrix-org/matrix-rust-sdk"
version = "0.1.0" version = "0.1.0"
[dependencies] [dependencies]
serde_json = "1.0.57" serde_json = "1.0.58"
http = "0.2.1" http = "0.2.1"
matrix-sdk-common = { version = "0.1.0", path = "../matrix_sdk_common" } matrix-sdk-common = { version = "0.1.0", path = "../matrix_sdk_common" }
matrix-sdk-test-macros = { version = "0.1.0", path = "../matrix_sdk_test_macros" } matrix-sdk-test-macros = { version = "0.1.0", path = "../matrix_sdk_test_macros" }
lazy_static = "1.4.0" lazy_static = "1.4.0"
serde = "1.0.115" serde = "1.0.116"