diff --git a/src/api/client/profile.rs b/src/api/client/profile.rs index 64bb327a..0b932944 100644 --- a/src/api/client/profile.rs +++ b/src/api/client/profile.rs @@ -43,7 +43,7 @@ pub(crate) async fn set_displayname_route( services .users - .update_displayname(&body.user_id, body.displayname.clone(), &all_joined_rooms) + .update_displayname(&body.user_id, body.displayname.as_deref(), &all_joined_rooms) .await; // Presence update @@ -87,13 +87,13 @@ pub(crate) async fn get_displayname_route( services .users - .set_displayname(&body.user_id, response.displayname.clone()); + .set_displayname(&body.user_id, response.displayname.as_deref()); services .users - .set_avatar_url(&body.user_id, response.avatar_url.clone()); + .set_avatar_url(&body.user_id, response.avatar_url.as_deref()); services .users - .set_blurhash(&body.user_id, response.blurhash.clone()); + .set_blurhash(&body.user_id, response.blurhash.as_deref()); return Ok(get_display_name::v3::Response { displayname: response.displayname }); } @@ -140,8 +140,8 @@ pub(crate) async fn set_avatar_url_route( .users .update_avatar_url( &body.user_id, - body.avatar_url.clone(), - body.blurhash.clone(), + body.avatar_url.as_deref(), + body.blurhash.as_deref(), &all_joined_rooms, ) .await; @@ -188,13 +188,13 @@ pub(crate) async fn get_avatar_url_route( services .users - .set_displayname(&body.user_id, response.displayname.clone()); + .set_displayname(&body.user_id, response.displayname.as_deref()); services .users - .set_avatar_url(&body.user_id, response.avatar_url.clone()); + .set_avatar_url(&body.user_id, response.avatar_url.as_deref()); services .users - .set_blurhash(&body.user_id, response.blurhash.clone()); + .set_blurhash(&body.user_id, response.blurhash.as_deref()); return Ok(get_avatar_url::v3::Response { avatar_url: response.avatar_url, @@ -250,22 +250,22 @@ pub(crate) async fn get_profile_route( services .users - .set_displayname(&body.user_id, response.displayname.clone()); + .set_displayname(&body.user_id, response.displayname.as_deref()); services .users - .set_avatar_url(&body.user_id, response.avatar_url.clone()); + .set_avatar_url(&body.user_id, response.avatar_url.as_deref()); services .users - .set_blurhash(&body.user_id, response.blurhash.clone()); + .set_blurhash(&body.user_id, response.blurhash.as_deref()); services .users - .set_timezone(&body.user_id, response.tz.clone()); + .set_timezone(&body.user_id, response.tz.as_deref()); for (profile_key, profile_key_value) in &response.custom_profile_fields { services.users.set_profile_key( &body.user_id, profile_key, - Some(profile_key_value.clone()), + Some(profile_key_value), ); } diff --git a/src/api/client/session/sso.rs b/src/api/client/session/sso.rs index a5476168..a166f6db 100644 --- a/src/api/client/session/sso.rs +++ b/src/api/client/session/sso.rs @@ -7,7 +7,7 @@ use base64::{Engine as _, engine::general_purpose::URL_SAFE_NO_PAD as b64}; use futures::{FutureExt, StreamExt, TryFutureExt, future::try_join}; use reqwest::header::{CONTENT_TYPE, HeaderValue}; use ruma::{ - Mxc, OwnedRoomId, OwnedUserId, ServerName, UserId, + Mxc, OwnedMxcUri, OwnedRoomId, OwnedUserId, ServerName, UserId, api::client::session::{sso_callback, sso_login, sso_login_with_provider}, }; use serde::{Deserialize, Serialize}; @@ -556,10 +556,10 @@ async fn set_avatar( .collect() .await; - let mxc_uri = mxc.to_string().into(); + let mxc_uri: OwnedMxcUri = mxc.to_string().into(); services .users - .update_avatar_url(user_id, Some(mxc_uri), None, &all_joined_rooms) + .update_avatar_url(user_id, Some(&mxc_uri), None, &all_joined_rooms) .await; Ok(()) diff --git a/src/api/client/unstable.rs b/src/api/client/unstable.rs index fd389d57..9d5802a0 100644 --- a/src/api/client/unstable.rs +++ b/src/api/client/unstable.rs @@ -16,7 +16,7 @@ use ruma::{ }, presence::PresenceState, }; -use tuwunel_core::{Err, Error, Result}; +use tuwunel_core::{Err, Error, Result, err}; use crate::Ruma; @@ -99,7 +99,7 @@ pub(crate) async fn set_timezone_key_route( services .users - .set_timezone(&body.user_id, body.tz.clone()); + .set_timezone(&body.user_id, body.tz.as_deref()); // Presence update services @@ -129,42 +129,40 @@ pub(crate) async fn set_profile_field_route( return Err!(Request(BadJson("Key names cannot be longer than 128 bytes"))); } - if body.value.field_name() == ProfileFieldName::DisplayName { - let all_joined_rooms: Vec = services - .state_cache - .rooms_joined(&body.user_id) - .map(Into::into) - .collect() - .await; + match &body.value { + | ProfileFieldValue::DisplayName(displayname) => { + let all_joined_rooms: Vec = services + .state_cache + .rooms_joined(&body.user_id) + .map(Into::into) + .collect() + .await; - services - .users - .update_displayname( + services + .users + .update_displayname(&body.user_id, Some(displayname), &all_joined_rooms) + .await; + }, + | ProfileFieldValue::AvatarUrl(avatar_url) => { + let all_joined_rooms: Vec = services + .state_cache + .rooms_joined(&body.user_id) + .map(Into::into) + .collect() + .await; + + services + .users + .update_avatar_url(&body.user_id, Some(avatar_url), None, &all_joined_rooms) + .await; + }, + | _ => { + services.users.set_profile_key( &body.user_id, - Some(body.value.value().to_string()), - &all_joined_rooms, - ) - .await; - } else if body.value.field_name() == ProfileFieldName::AvatarUrl { - let mxc = ruma::OwnedMxcUri::from(body.value.value().to_string()); - - let all_joined_rooms: Vec = services - .state_cache - .rooms_joined(&body.user_id) - .map(Into::into) - .collect() - .await; - - services - .users - .update_avatar_url(&body.user_id, Some(mxc), None, &all_joined_rooms) - .await; - } else { - services.users.set_profile_key( - &body.user_id, - body.value.field_name().as_str(), - Some(body.value.value().into_owned()), - ); + body.value.field_name().as_str(), + Some(&body.value.value()), + ); + }, } // Presence update @@ -191,34 +189,38 @@ pub(crate) async fn delete_profile_field_route( return Err!(Request(Forbidden("You cannot update the profile of another user"))); } - if body.field == ProfileFieldName::DisplayName { - let all_joined_rooms: Vec = services - .state_cache - .rooms_joined(&body.user_id) - .map(Into::into) - .collect() - .await; + match body.field { + | ProfileFieldName::DisplayName => { + let all_joined_rooms: Vec = services + .state_cache + .rooms_joined(&body.user_id) + .map(Into::into) + .collect() + .await; - services - .users - .update_displayname(&body.user_id, None, &all_joined_rooms) - .await; - } else if body.field == ProfileFieldName::AvatarUrl { - let all_joined_rooms: Vec = services - .state_cache - .rooms_joined(&body.user_id) - .map(Into::into) - .collect() - .await; + services + .users + .update_displayname(&body.user_id, None, &all_joined_rooms) + .await; + }, + | ProfileFieldName::AvatarUrl => { + let all_joined_rooms: Vec = services + .state_cache + .rooms_joined(&body.user_id) + .map(Into::into) + .collect() + .await; - services - .users - .update_avatar_url(&body.user_id, None, None, &all_joined_rooms) - .await; - } else { - services - .users - .set_profile_key(&body.user_id, body.field.as_str(), None); + services + .users + .update_avatar_url(&body.user_id, None, None, &all_joined_rooms) + .await; + }, + | _ => { + services + .users + .set_profile_key(&body.user_id, body.field.as_str(), None); + }, } // Presence update @@ -262,19 +264,19 @@ pub(crate) async fn get_timezone_key_route( services .users - .set_displayname(&body.user_id, response.displayname.clone()); + .set_displayname(&body.user_id, response.displayname.as_deref()); services .users - .set_avatar_url(&body.user_id, response.avatar_url.clone()); + .set_avatar_url(&body.user_id, response.avatar_url.as_deref()); services .users - .set_blurhash(&body.user_id, response.blurhash.clone()); + .set_blurhash(&body.user_id, response.blurhash.as_deref()); services .users - .set_timezone(&body.user_id, response.tz.clone()); + .set_timezone(&body.user_id, response.tz.as_deref()); return Ok(get_timezone_key::unstable::Response { tz: response.tz }); } @@ -323,43 +325,34 @@ pub(crate) async fn get_profile_field_route( services .users - .set_displayname(&body.user_id, response.displayname.clone()); + .set_displayname(&body.user_id, response.displayname.as_deref()); services .users - .set_avatar_url(&body.user_id, response.avatar_url.clone()); + .set_avatar_url(&body.user_id, response.avatar_url.as_deref()); services .users - .set_blurhash(&body.user_id, response.blurhash.clone()); + .set_blurhash(&body.user_id, response.blurhash.as_deref()); services .users - .set_timezone(&body.user_id, response.tz.clone()); + .set_timezone(&body.user_id, response.tz.as_deref()); - let profile_key_value: Option = match response + let value = response .custom_profile_fields .get(body.field.as_str()) - { - | Some(value) => { - services.users.set_profile_key( - &body.user_id, - body.field.as_str(), - Some(value.clone()), - ); + .ok_or_else(|| { + err!(Request(NotFound("The requested profile key does not exist."))) + })?; - Some(ProfileFieldValue::new(body.field.as_str(), value.clone())?) - }, - | _ => { - return Err!(Request(NotFound("The requested profile key does not exist."))); - }, - }; + services + .users + .set_profile_key(&body.user_id, body.field.as_str(), Some(value)); - if profile_key_value.is_none() { - return Err!(Request(NotFound("The requested profile key does not exist."))); - } + let profile_key_value = ProfileFieldValue::new(body.field.as_str(), value.clone())?; - return Ok(get_profile_field::v3::Response { value: profile_key_value }); + return Ok(get_profile_field::v3::Response { value: Some(profile_key_value) }); } } @@ -369,20 +362,13 @@ pub(crate) async fn get_profile_field_route( return Err!(Request(NotFound("Profile was not found."))); } - let profile_key_value: Option = match services + let value = services .users .profile_key(&body.user_id, body.field.as_str()) .await - { - | Ok(value) => Some(ProfileFieldValue::new(body.field.as_str(), value)?), - | _ => { - return Err!(Request(NotFound("The requested profile key does not exist."))); - }, - }; + .map_err(|_| err!(Request(NotFound("The requested profile key does not exist."))))?; - if profile_key_value.is_none() { - return Err!(Request(NotFound("The requested profile key does not exist."))); - } + let profile_key_value = ProfileFieldValue::new(body.field.as_str(), value)?; - Ok(get_profile_field::v3::Response { value: profile_key_value }) + Ok(get_profile_field::v3::Response { value: Some(profile_key_value) }) } diff --git a/src/service/users/profile.rs b/src/service/users/profile.rs index f35725bb..0c69f0ea 100644 --- a/src/service/users/profile.rs +++ b/src/service/users/profile.rs @@ -1,6 +1,6 @@ use futures::{FutureExt, Stream, StreamExt, TryFutureExt, TryStreamExt, future::join3}; use ruma::{ - OwnedMxcUri, OwnedRoomId, UserId, + MxcUri, OwnedMxcUri, OwnedRoomId, UserId, events::room::member::{MembershipState, RoomMemberEventContent}, }; use tuwunel_core::{ @@ -17,7 +17,7 @@ use tuwunel_database::{Deserialized, Ignore, Interfix, Json}; pub async fn update_displayname( &self, user_id: &UserId, - displayname: Option, + displayname: Option<&str>, rooms: &[OwnedRoomId], ) { let (current_avatar_url, current_blurhash, current_displayname) = join3( @@ -27,13 +27,13 @@ pub async fn update_displayname( ) .await; - if displayname == current_displayname { + if displayname == current_displayname.as_deref() { return; } self.services .users - .set_displayname(user_id, displayname.clone()); + .set_displayname(user_id, displayname); // Send a new join membership event into rooms let avatar_url = ¤t_avatar_url; @@ -44,7 +44,7 @@ pub async fn update_displayname( .try_stream() .and_then(async |room_id: &OwnedRoomId| { let pdu = PduBuilder::state(user_id.to_string(), &RoomMemberEventContent { - displayname: displayname.clone(), + displayname: displayname.map(ToOwned::to_owned), membership: MembershipState::Join, avatar_url: avatar_url.clone(), blurhash: blurhash.clone(), @@ -68,7 +68,7 @@ pub async fn update_displayname( /// Sets a new displayname or removes it if displayname is None. You still /// need to notify all rooms of this change. #[implement(super::Service)] -pub fn set_displayname(&self, user_id: &UserId, displayname: Option) { +pub fn set_displayname(&self, user_id: &UserId, displayname: Option<&str>) { if let Some(displayname) = displayname { self.db .userid_displayname @@ -92,8 +92,8 @@ pub async fn displayname(&self, user_id: &UserId) -> Result { pub async fn update_avatar_url( &self, user_id: &UserId, - avatar_url: Option, - blurhash: Option, + avatar_url: Option<&MxcUri>, + blurhash: Option<&str>, rooms: &[OwnedRoomId], ) { let (current_avatar_url, current_blurhash, current_displayname) = join3( @@ -103,30 +103,27 @@ pub async fn update_avatar_url( ) .await; - if current_avatar_url == avatar_url && current_blurhash == blurhash { + if current_avatar_url.as_deref() == avatar_url && current_blurhash.as_deref() == blurhash { return; } self.services .users - .set_avatar_url(user_id, avatar_url.clone()); + .set_avatar_url(user_id, avatar_url); self.services .users - .set_blurhash(user_id, blurhash.clone()); + .set_blurhash(user_id, blurhash); // Send a new join membership event into rooms - let avatar_url = &avatar_url; - let blurhash = &blurhash; - let displayname = ¤t_displayname; let rooms: Vec<_> = rooms .iter() .try_stream() .and_then(async |room_id: &OwnedRoomId| { let pdu = PduBuilder::state(user_id.to_string(), &RoomMemberEventContent { - avatar_url: avatar_url.clone(), - blurhash: blurhash.clone(), + avatar_url: avatar_url.map(ToOwned::to_owned), + blurhash: blurhash.map(ToOwned::to_owned), membership: MembershipState::Join, - displayname: displayname.clone(), + displayname: current_displayname.clone(), join_authorized_via_users_server: None, reason: None, is_direct: None, @@ -146,16 +143,13 @@ pub async fn update_avatar_url( /// Sets a new avatar_url or removes it if avatar_url is None. #[implement(super::Service)] -pub fn set_avatar_url(&self, user_id: &UserId, avatar_url: Option) { - match avatar_url { - | Some(avatar_url) => { - self.db - .userid_avatarurl - .insert(user_id, &avatar_url); - }, - | _ => { - self.db.userid_avatarurl.remove(user_id); - }, +pub fn set_avatar_url(&self, user_id: &UserId, avatar_url: Option<&MxcUri>) { + if let Some(avatar_url) = avatar_url { + self.db + .userid_avatarurl + .insert(user_id, avatar_url); + } else { + self.db.userid_avatarurl.remove(user_id); } } @@ -171,7 +165,7 @@ pub async fn avatar_url(&self, user_id: &UserId) -> Result { /// Sets a new avatar_url or removes it if avatar_url is None. #[implement(super::Service)] -pub fn set_blurhash(&self, user_id: &UserId, blurhash: Option) { +pub fn set_blurhash(&self, user_id: &UserId, blurhash: Option<&str>) { if let Some(blurhash) = blurhash { self.db.userid_blurhash.insert(user_id, blurhash); } else { @@ -191,14 +185,14 @@ pub async fn blurhash(&self, user_id: &UserId) -> Result { /// Sets a new timezone or removes it if timezone is None. #[implement(super::Service)] -pub fn set_timezone(&self, user_id: &UserId, timezone: Option) { +pub fn set_timezone(&self, user_id: &UserId, timezone: Option<&str>) { // TODO: insert to the stable MSC4175 key when it's stable let key = (user_id, "us.cloke.msc4175.tz"); if let Some(timezone) = timezone { self.db .useridprofilekey_value - .put_raw(key, &timezone); + .put_raw(key, timezone); } else { self.db.useridprofilekey_value.del(key); } @@ -243,7 +237,7 @@ pub fn set_profile_key( &self, user_id: &UserId, profile_key: &str, - profile_key_value: Option, + profile_key_value: Option<&serde_json::Value>, ) { // TODO: insert to the stable MSC4175 key when it's stable let key = (user_id, profile_key); diff --git a/src/service/users/register.rs b/src/service/users/register.rs index 58039fc1..fa8804c9 100644 --- a/src/service/users/register.rs +++ b/src/service/users/register.rs @@ -86,7 +86,7 @@ pub async fn full_register( self.services .users - .set_displayname(user_id, Some(displayname)); + .set_displayname(user_id, Some(&displayname)); } // Initial account data