Merge branch 'bump-ruma'

master
Damir Jelić 2021-04-06 12:34:58 +02:00
commit fdb1e3482e
17 changed files with 71 additions and 106 deletions

View File

@ -2,11 +2,16 @@ use std::{convert::TryFrom, env, process::exit};
use url::Url; use url::Url;
use matrix_sdk::{self, api::r0::profile, identifiers::UserId, Client, Result as MatrixResult}; use matrix_sdk::{
self,
api::r0::profile,
identifiers::{MxcUri, UserId},
Client, Result as MatrixResult,
};
#[derive(Debug)] #[derive(Debug)]
struct UserProfile { struct UserProfile {
avatar_url: Option<String>, avatar_url: Option<MxcUri>,
displayname: Option<String>, displayname: Option<String>,
} }

View File

@ -56,8 +56,8 @@ use tracing::{debug, warn};
use tracing::{error, info, instrument}; use tracing::{error, info, instrument};
use matrix_sdk_base::{ use matrix_sdk_base::{
deserialized_responses::SyncResponse, events::AnyMessageEventContent, BaseClient, deserialized_responses::SyncResponse, events::AnyMessageEventContent, identifiers::MxcUri,
BaseClientConfig, Session, Store, BaseClient, BaseClientConfig, Session, Store,
}; };
#[cfg(feature = "encryption")] #[cfg(feature = "encryption")]
@ -516,7 +516,7 @@ impl Client {
/// } /// }
/// # }) /// # })
/// ``` /// ```
pub async fn avatar_url(&self) -> Result<Option<String>> { pub async fn avatar_url(&self) -> Result<Option<MxcUri>> {
let user_id = self.user_id().await.ok_or(Error::AuthenticationRequired)?; let user_id = self.user_id().await.ok_or(Error::AuthenticationRequired)?;
let request = get_avatar_url::Request::new(&user_id); let request = get_avatar_url::Request::new(&user_id);
let response = self.send(request, None).await?; let response = self.send(request, None).await?;
@ -553,22 +553,14 @@ impl Client {
/// ``` /// ```
pub async fn avatar(&self, width: Option<u32>, height: Option<u32>) -> Result<Option<Vec<u8>>> { pub async fn avatar(&self, width: Option<u32>, height: Option<u32>) -> Result<Option<Vec<u8>>> {
// TODO: try to offer the avatar from cache, requires avatar cache // TODO: try to offer the avatar from cache, requires avatar cache
if let Some((server_name, media_id)) = self if let Some(url) = self.avatar_url().await? {
.avatar_url()
.await?
.and_then(|url| crate::parse_mxc(&url))
{
if let (Some(width), Some(height)) = (width, height) { if let (Some(width), Some(height)) = (width, height) {
let request = get_content_thumbnail::Request::new( let request =
&media_id, get_content_thumbnail::Request::from_url(&url, width.into(), height.into());
&server_name,
width.into(),
height.into(),
);
let response = self.send(request, None).await?; let response = self.send(request, None).await?;
Ok(Some(response.file)) Ok(Some(response.file))
} else { } else {
let request = get_content::Request::new(&media_id, &server_name); let request = get_content::Request::from_url(&url);
let response = self.send(request, None).await?; let response = self.send(request, None).await?;
Ok(Some(response.file)) Ok(Some(response.file))
} }
@ -583,7 +575,7 @@ impl Client {
} }
/// Sets the mxc avatar url of the client's owner. The avatar gets unset if `url` is `None`. /// Sets the mxc avatar url of the client's owner. The avatar gets unset if `url` is `None`.
pub async fn set_avatar_url(&self, url: Option<&str>) -> Result<()> { pub async fn set_avatar_url(&self, url: Option<&MxcUri>) -> Result<()> {
let user_id = self.user_id().await.ok_or(Error::AuthenticationRequired)?; let user_id = self.user_id().await.ok_or(Error::AuthenticationRequired)?;
let request = set_avatar_url::Request::new(&user_id, url); let request = set_avatar_url::Request::new(&user_id, url);
self.send(request, None).await?; self.send(request, None).await?;
@ -2261,6 +2253,7 @@ mod test {
get_public_rooms, get_public_rooms_filtered, register::RegistrationKind, Client, Session, get_public_rooms, get_public_rooms_filtered, register::RegistrationKind, Client, Session,
SyncSettings, Url, SyncSettings, Url,
}; };
use matrix_sdk_base::identifiers::mxc_uri;
use matrix_sdk_common::{ use matrix_sdk_common::{
api::r0::{ api::r0::{
account::register::Request as RegistrationRequest, account::register::Request as RegistrationRequest,
@ -3043,9 +3036,9 @@ mod test {
let room = client.get_joined_room(&room_id).unwrap(); let room = client.get_joined_room(&room_id).unwrap();
let avatar_url = "https://example.org/avatar"; let avatar_url = mxc_uri!("mxc://example.org/avA7ar");
let member_event = MemberEventContent { let member_event = MemberEventContent {
avatar_url: Some(avatar_url.to_string()), avatar_url: Some(avatar_url),
membership: MembershipState::Join, membership: MembershipState::Join,
is_direct: None, is_direct: None,
displayname: None, displayname: None,

View File

@ -109,20 +109,3 @@ pub use sas::Sas;
#[cfg(not(target_arch = "wasm32"))] #[cfg(not(target_arch = "wasm32"))]
pub(crate) const VERSION: &str = env!("CARGO_PKG_VERSION"); pub(crate) const VERSION: &str = env!("CARGO_PKG_VERSION");
// TODO: remove this function once we can use the Mxc type: https://github.com/ruma/ruma/pull/439
pub(crate) fn parse_mxc(url: &str) -> Option<(identifiers::ServerNameBox, String)> {
use std::convert::TryFrom;
if let Ok(url) = url::Url::parse(&url) {
if url.scheme() == "mxc" {
if let Some(server_name) = url
.host_str()
.and_then(|host| <identifiers::ServerNameBox>::try_from(host).ok())
{
let media_id = url.path().to_owned();
return Some((server_name, media_id));
}
}
}
None
}

View File

@ -94,20 +94,14 @@ impl Common {
/// ``` /// ```
pub async fn avatar(&self, width: Option<u32>, height: Option<u32>) -> Result<Option<Vec<u8>>> { pub async fn avatar(&self, width: Option<u32>, height: Option<u32>) -> Result<Option<Vec<u8>>> {
// TODO: try to offer the avatar from cache, requires avatar cache // TODO: try to offer the avatar from cache, requires avatar cache
if let Some((server_name, media_id)) = if let Some(url) = self.avatar_url() {
self.avatar_url().and_then(|url| crate::parse_mxc(&url))
{
if let (Some(width), Some(height)) = (width, height) { if let (Some(width), Some(height)) = (width, height) {
let request = get_content_thumbnail::Request::new( let request =
&media_id, get_content_thumbnail::Request::from_url(&url, width.into(), height.into());
&server_name,
width.into(),
height.into(),
);
let response = self.client.send(request, None).await?; let response = self.client.send(request, None).await?;
Ok(Some(response.file)) Ok(Some(response.file))
} else { } else {
let request = get_content::Request::new(&media_id, &server_name); let request = get_content::Request::from_url(&url);
let response = self.client.send(request, None).await?; let response = self.client.send(request, None).await?;
Ok(Some(response.file)) Ok(Some(response.file))
} }

View File

@ -12,7 +12,7 @@ use matrix_sdk_common::{
read_marker::set_read_marker, read_marker::set_read_marker,
receipt::create_receipt, receipt::create_receipt,
redact::redact_event, redact::redact_event,
state::send_state_event_for_key, state::send_state_event,
typing::create_typing_event::{Request as TypingRequest, Typing}, typing::create_typing_event::{Request as TypingRequest, Typing},
}, },
assign, assign,
@ -560,18 +560,21 @@ impl Joined {
/// # Example /// # Example
/// ///
/// ```no_run /// ```no_run
/// use matrix_sdk::events::{ /// use matrix_sdk::{
/// events::{
/// AnyStateEventContent, /// AnyStateEventContent,
/// room::member::{MemberEventContent, MembershipState}, /// room::member::{MemberEventContent, MembershipState},
/// },
/// identifiers::mxc_uri,
/// }; /// };
/// # futures::executor::block_on(async { /// # futures::executor::block_on(async {
/// # let homeserver = url::Url::parse("http://localhost:8080").unwrap(); /// # let homeserver = url::Url::parse("http://localhost:8080").unwrap();
/// # let mut client = matrix_sdk::Client::new(homeserver).unwrap(); /// # let mut client = matrix_sdk::Client::new(homeserver).unwrap();
/// # let room_id = matrix_sdk::identifiers::room_id!("!test:localhost"); /// # let room_id = matrix_sdk::identifiers::room_id!("!test:localhost");
/// ///
/// let avatar_url = "https://example.org/avatar"; /// let avatar_url = mxc_uri!("mxc://example.org/avatar");
/// let member_event = MemberEventContent { /// let member_event = MemberEventContent {
/// avatar_url: Some(avatar_url.to_string()), /// avatar_url: Some(avatar_url),
/// membership: MembershipState::Join, /// membership: MembershipState::Join,
/// is_direct: None, /// is_direct: None,
/// displayname: None, /// displayname: None,
@ -589,10 +592,9 @@ impl Joined {
&self, &self,
content: impl Into<AnyStateEventContent>, content: impl Into<AnyStateEventContent>,
state_key: &str, state_key: &str,
) -> Result<send_state_event_for_key::Response> { ) -> Result<send_state_event::Response> {
let content = content.into(); let content = content.into();
let request = let request = send_state_event::Request::new(self.inner.room_id(), state_key, &content);
send_state_event_for_key::Request::new(self.inner.room_id(), state_key, &content);
self.client.send(request, None).await self.client.send(request, None).await
} }

View File

@ -63,20 +63,14 @@ impl RoomMember {
/// ``` /// ```
pub async fn avatar(&self, width: Option<u32>, height: Option<u32>) -> Result<Option<Vec<u8>>> { pub async fn avatar(&self, width: Option<u32>, height: Option<u32>) -> Result<Option<Vec<u8>>> {
// TODO: try to offer the avatar from cache, requires avatar cache // TODO: try to offer the avatar from cache, requires avatar cache
if let Some((server_name, media_id)) = if let Some(url) = self.avatar_url() {
self.avatar_url().and_then(|url| crate::parse_mxc(&url))
{
if let (Some(width), Some(height)) = (width, height) { if let (Some(width), Some(height)) = (width, height) {
let request = get_content_thumbnail::Request::new( let request =
&media_id, get_content_thumbnail::Request::from_url(&url, width.into(), height.into());
&server_name,
width.into(),
height.into(),
);
let response = self.client.send(request, None).await?; let response = self.client.send(request, None).await?;
Ok(Some(response.file)) Ok(Some(response.file))
} else { } else {
let request = get_content::Request::new(&media_id, &server_name); let request = get_content::Request::from_url(url);
let response = self.client.send(request, None).await?; let response = self.client.send(request, None).await?;
Ok(Some(response.file)) Ok(Some(response.file))
} }

View File

@ -20,7 +20,7 @@ use matrix_sdk_common::{
room::{member::MemberEventContent, power_levels::PowerLevelsEventContent}, room::{member::MemberEventContent, power_levels::PowerLevelsEventContent},
SyncStateEvent, SyncStateEvent,
}, },
identifiers::UserId, identifiers::{MxcUri, UserId},
}; };
use crate::deserialized_responses::MemberEvent; use crate::deserialized_responses::MemberEvent;
@ -65,10 +65,10 @@ impl RoomMember {
} }
/// Get the avatar url of the member, if there is one. /// Get the avatar url of the member, if there is one.
pub fn avatar_url(&self) -> Option<&str> { pub fn avatar_url(&self) -> Option<&MxcUri> {
match self.profile.as_ref() { match self.profile.as_ref() {
Some(p) => p.avatar_url.as_deref(), Some(p) => p.avatar_url.as_ref(),
None => self.event.content.avatar_url.as_deref(), None => self.event.content.avatar_url.as_ref(),
} }
} }

View File

@ -6,7 +6,7 @@ use matrix_sdk_common::{
create::CreateEventContent, guest_access::GuestAccess, create::CreateEventContent, guest_access::GuestAccess,
history_visibility::HistoryVisibility, join_rules::JoinRule, history_visibility::HistoryVisibility, join_rules::JoinRule,
}, },
identifiers::UserId, identifiers::{MxcUri, UserId},
}; };
pub use normal::{Room, RoomInfo, RoomType}; pub use normal::{Room, RoomInfo, RoomType};
@ -29,7 +29,7 @@ use matrix_sdk_common::{
#[derive(Clone, Debug, Serialize, Deserialize)] #[derive(Clone, Debug, Serialize, Deserialize)]
pub struct BaseRoomInfo { pub struct BaseRoomInfo {
/// The avatar URL of this room. /// The avatar URL of this room.
pub avatar_url: Option<String>, pub avatar_url: Option<MxcUri>,
/// The canonical alias of this room. /// The canonical alias of this room.
pub canonical_alias: Option<RoomAliasId>, pub canonical_alias: Option<RoomAliasId>,
/// The `m.room.create` event content of this room. /// The `m.room.create` event content of this room.

View File

@ -31,7 +31,7 @@ use matrix_sdk_common::{
}, },
AnyStateEventContent, AnySyncStateEvent, EventType, AnyStateEventContent, AnySyncStateEvent, EventType,
}, },
identifiers::{RoomAliasId, RoomId, UserId}, identifiers::{MxcUri, RoomAliasId, RoomId, UserId},
}; };
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use tracing::info; use tracing::info;
@ -148,7 +148,7 @@ impl Room {
} }
/// Get the avatar url of this room. /// Get the avatar url of this room.
pub fn avatar_url(&self) -> Option<String> { pub fn avatar_url(&self) -> Option<MxcUri> {
self.inner.read().unwrap().base_info.avatar_url.clone() self.inner.read().unwrap().base_info.avatar_url.clone()
} }

View File

@ -22,7 +22,7 @@ async-trait = "0.1.42"
[dependencies.ruma] [dependencies.ruma]
version = "0.0.2" version = "0.0.2"
git = "https://github.com/ruma/ruma" git = "https://github.com/ruma/ruma"
rev = "92ee92ad7eb90b3c80abbd7eb116d886c79bf4fd" rev = "2f1b9f097930bf7908ca539f2ab7bb0ccf5d8b25"
features = ["client-api", "compat", "unstable-pre-spec"] features = ["client-api", "compat", "unstable-pre-spec"]
[target.'cfg(not(target_arch = "wasm32"))'.dependencies] [target.'cfg(not(target_arch = "wasm32"))'.dependencies]

View File

@ -174,6 +174,11 @@ pub(crate) enum SessionCreationError {
one-time key is missing" one-time key is missing"
)] )]
OneTimeKeyMissing(UserId, Box<DeviceId>), OneTimeKeyMissing(UserId, Box<DeviceId>),
#[error(
"Tried to create a new Olm session for {0} {1}, but the one-time \
key algorithm is unsupported"
)]
OneTimeKeyUnknown(UserId, Box<DeviceId>),
#[error("Failed to verify the one-time key signatures for {0} {1}: {2:?}")] #[error("Failed to verify the one-time key signatures for {0} {1}: {2:?}")]
InvalidSignature(UserId, Box<DeviceId>, SignatureError), InvalidSignature(UserId, Box<DeviceId>, SignatureError),
#[error( #[error(

View File

@ -800,10 +800,7 @@ impl ReadOnlyAccount {
let mut signatures = BTreeMap::new(); let mut signatures = BTreeMap::new();
signatures.insert((*self.user_id).clone(), signature_map); signatures.insert((*self.user_id).clone(), signature_map);
let signed_key = SignedKey { let signed_key = SignedKey::new(key.to_owned(), signatures);
key: key.to_owned(),
signatures,
};
one_time_key_map.insert( one_time_key_map.insert(
DeviceKeyId::from_parts( DeviceKeyId::from_parts(
@ -894,6 +891,12 @@ impl ReadOnlyAccount {
device.device_id().into(), device.device_id().into(),
)); ));
} }
_ => {
return Err(SessionCreationError::OneTimeKeyUnknown(
device.user_id().to_owned(),
device.device_id().into(),
));
}
}; };
device.verify_one_time_key(&one_time_key).map_err(|e| { device.verify_one_time_key(&one_time_key).map_err(|e| {

View File

@ -99,10 +99,7 @@ pub(crate) mod test {
.unwrap() .unwrap()
.1 .1
.to_owned(); .to_owned();
let one_time_key = SignedKey { let one_time_key = SignedKey::new(one_time_key, BTreeMap::new());
key: one_time_key,
signatures: BTreeMap::new(),
};
let sender_key = bob.identity_keys().curve25519().to_owned(); let sender_key = bob.identity_keys().curve25519().to_owned();
let session = alice let session = alice
.create_outbound_session_helper(&sender_key, &one_time_key) .create_outbound_session_helper(&sender_key, &one_time_key)
@ -177,10 +174,7 @@ pub(crate) mod test {
.1 .1
.to_owned(); .to_owned();
let one_time_key = SignedKey { let one_time_key = SignedKey::new(one_time_key, BTreeMap::new());
key: one_time_key,
signatures: BTreeMap::new(),
};
let mut bob_session = bob let mut bob_session = bob
.create_outbound_session_helper(alice_keys.curve25519(), &one_time_key) .create_outbound_session_helper(alice_keys.curve25519(), &one_time_key)

View File

@ -384,12 +384,7 @@ impl Signing {
self.public_key().to_string(), self.public_key().to_string(),
); );
CrossSigningKey { CrossSigningKey::new(user_id, vec![usage], keys, BTreeMap::new())
user_id,
usage: vec![usage],
keys,
signatures: BTreeMap::new(),
}
} }
#[cfg(test)] #[cfg(test)]

View File

@ -729,10 +729,7 @@ mod test {
.unwrap() .unwrap()
.1 .1
.to_owned(); .to_owned();
let one_time_key = SignedKey { let one_time_key = SignedKey::new(one_time_key, BTreeMap::new());
key: one_time_key,
signatures: BTreeMap::new(),
};
let sender_key = bob.identity_keys().curve25519().to_owned(); let sender_key = bob.identity_keys().curve25519().to_owned();
let session = alice let session = alice
.create_outbound_session_helper(&sender_key, &one_time_key) .create_outbound_session_helper(&sender_key, &one_time_key)

View File

@ -407,7 +407,7 @@ lazy_static! {
lazy_static! { lazy_static! {
pub static ref PRESENCE: JsonValue = json!({ pub static ref PRESENCE: JsonValue = json!({
"content": { "content": {
"avatar_url": "mxc://localhost:wefuiwegh8742w", "avatar_url": "mxc://localhost/wefuiwegh8742w",
"currently_active": false, "currently_active": false,
"last_active_ago": 1, "last_active_ago": 1,
"presence": "online", "presence": "online",

View File

@ -210,7 +210,7 @@ lazy_static! {
"content": { "content": {
"membership": "leave", "membership": "leave",
"reason": "offline", "reason": "offline",
"avatar_url": "avatar.com", "avatar_url": "mxc://avatar.com/d0dV9jLpe",
"displayname": "example" "displayname": "example"
}, },
"event_id": "$1585345508297748AIUBh:matrix.org", "event_id": "$1585345508297748AIUBh:matrix.org",
@ -221,7 +221,7 @@ lazy_static! {
"unsigned": { "unsigned": {
"replaces_state": "$1585345354296486IGZfp:localhost", "replaces_state": "$1585345354296486IGZfp:localhost",
"prev_content": { "prev_content": {
"avatar_url": "avatar.com", "avatar_url": "mxc://avatar.com/d0dV9jLpe",
"displayname": "example", "displayname": "example",
"membership": "join" "membership": "join"
}, },
@ -268,7 +268,7 @@ lazy_static! {
"events": [ "events": [
{ {
"content": { "content": {
"avatar_url": "mxc://localhost:wefuiwegh8742w", "avatar_url": "mxc://localhost/wefuiwegh8742w",
"currently_active": false, "currently_active": false,
"last_active_ago": 1, "last_active_ago": 1,
"presence": "online", "presence": "online",
@ -526,7 +526,7 @@ lazy_static! {
"events": [ "events": [
{ {
"content": { "content": {
"avatar_url": "mxc://localhost:wefuiwegh8742w", "avatar_url": "mxc://localhost/wefuiwegh8742w",
"currently_active": false, "currently_active": false,
"last_active_ago": 1, "last_active_ago": 1,
"presence": "online", "presence": "online",
@ -743,7 +743,7 @@ lazy_static! {
"events": [ "events": [
{ {
"content": { "content": {
"avatar_url": "mxc://localhost:wefuiwegh8742w", "avatar_url": "mxc://localhost/wefuiwegh8742w",
"currently_active": false, "currently_active": false,
"last_active_ago": 1, "last_active_ago": 1,
"presence": "online", "presence": "online",
@ -966,7 +966,7 @@ lazy_static! {
"content": { "content": {
"membership": "leave", "membership": "leave",
"reason": "offline", "reason": "offline",
"avatar_url": "avatar.com", "avatar_url": "mxc://avatar.com/ursn982srs2S",
"displayname": "example" "displayname": "example"
}, },
"event_id": "$1585345508297748AIUBh:matrix.org", "event_id": "$1585345508297748AIUBh:matrix.org",
@ -977,7 +977,7 @@ lazy_static! {
"unsigned": { "unsigned": {
"replaces_state": "$1585345354296486IGZfp:localhost", "replaces_state": "$1585345354296486IGZfp:localhost",
"prev_content": { "prev_content": {
"avatar_url": "avatar.com", "avatar_url": "mxc://avatar.com/ursn982srs2S",
"displayname": "example", "displayname": "example",
"membership": "join" "membership": "join"
}, },
@ -1023,7 +1023,7 @@ lazy_static! {
"events": [ "events": [
{ {
"content": { "content": {
"avatar_url": "mxc://localhost:wefuiwegh8742w", "avatar_url": "mxc://localhost/wefuiwegh8742w",
"currently_active": false, "currently_active": false,
"last_active_ago": 1, "last_active_ago": 1,
"presence": "online", "presence": "online",