implement MSC4133 only with MSC4175 for GET/PUT/DELETE

Signed-off-by: strawberry <strawberry@puppygock.gay>
This commit is contained in:
strawberry 2024-09-07 09:26:50 -04:00
parent 5ae9a5ff31
commit f163ebf3bb
7 changed files with 217 additions and 10 deletions

View file

@ -1,5 +1,5 @@
use axum::extract::State;
use conduit::{pdu::PduBuilder, warn, Error, Result};
use conduit::{pdu::PduBuilder, warn, Err, Error, Result};
use ruma::{
api::{
client::{
@ -26,20 +26,25 @@ pub(crate) async fn set_displayname_route(
State(services): State<crate::State>, body: Ruma<set_display_name::v3::Request>,
) -> Result<set_display_name::v3::Response> {
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
if *sender_user != body.user_id && body.appservice_info.is_none() {
return Err!(Request(Forbidden("You cannot update the profile of another user")));
}
let all_joined_rooms: Vec<OwnedRoomId> = services
.rooms
.state_cache
.rooms_joined(sender_user)
.rooms_joined(&body.user_id)
.filter_map(Result::ok)
.collect();
update_displayname(&services, sender_user.clone(), body.displayname.clone(), all_joined_rooms).await?;
update_displayname(&services, body.user_id.clone(), body.displayname.clone(), all_joined_rooms).await?;
if services.globals.allow_local_presence() {
// Presence update
services
.presence
.ping_presence(sender_user, &PresenceState::Online)?;
.ping_presence(&body.user_id, &PresenceState::Online)?;
}
Ok(set_display_name::v3::Response {})
@ -110,16 +115,21 @@ pub(crate) async fn set_avatar_url_route(
State(services): State<crate::State>, body: Ruma<set_avatar_url::v3::Request>,
) -> Result<set_avatar_url::v3::Response> {
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
if *sender_user != body.user_id && body.appservice_info.is_none() {
return Err!(Request(Forbidden("You cannot update the profile of another user")));
}
let all_joined_rooms: Vec<OwnedRoomId> = services
.rooms
.state_cache
.rooms_joined(sender_user)
.rooms_joined(&body.user_id)
.filter_map(Result::ok)
.collect();
update_avatar_url(
&services,
sender_user.clone(),
body.user_id.clone(),
body.avatar_url.clone(),
body.blurhash.clone(),
all_joined_rooms,
@ -130,7 +140,7 @@ pub(crate) async fn set_avatar_url_route(
// Presence update
services
.presence
.ping_presence(sender_user, &PresenceState::Online)?;
.ping_presence(&body.user_id, &PresenceState::Online)?;
}
Ok(set_avatar_url::v3::Response {})
@ -196,7 +206,7 @@ pub(crate) async fn get_avatar_url_route(
/// # `GET /_matrix/client/v3/profile/{userId}`
///
/// Returns the displayname, avatar_url and blurhash of the user.
/// Returns the displayname, avatar_url, blurhash, and tz of the user.
///
/// - If user is on another server and we do not have a local copy already,
/// fetch profile over federation.
@ -232,11 +242,16 @@ pub(crate) async fn get_profile_route(
.users
.set_blurhash(&body.user_id, response.blurhash.clone())
.await?;
services
.users
.set_timezone(&body.user_id, response.tz.clone())
.await?;
return Ok(get_profile::v3::Response {
displayname: response.displayname,
avatar_url: response.avatar_url,
blurhash: response.blurhash,
tz: response.tz,
});
}
}
@ -251,6 +266,7 @@ pub(crate) async fn get_profile_route(
avatar_url: services.users.avatar_url(&body.user_id)?,
blurhash: services.users.blurhash(&body.user_id)?,
displayname: services.users.displayname(&body.user_id)?,
tz: services.users.timezone(&body.user_id)?,
})
}

View file

@ -1,9 +1,18 @@
use axum::extract::State;
use axum_client_ip::InsecureClientIp;
use conduit::warn;
use conduit::{warn, Err};
use ruma::{
api::client::{error::ErrorKind, membership::mutual_rooms, room::get_summary},
api::{
client::{
error::ErrorKind,
membership::mutual_rooms,
profile::{delete_timezone_key, get_timezone_key, set_timezone_key},
room::get_summary,
},
federation,
},
events::room::member::MembershipState,
presence::PresenceState,
OwnedRoomId,
};
@ -161,3 +170,118 @@ pub(crate) async fn get_room_summary(
.unwrap_or_else(|_e| None),
})
}
/// # `DELETE /_matrix/client/unstable/uk.tcpip.msc4133/profile/:user_id/us.cloke.msc4175.tz`
///
/// Deletes the `tz` (timezone) of a user, as per MSC4133 and MSC4175.
///
/// - Also makes sure other users receive the update using presence EDUs
pub(crate) async fn delete_timezone_key_route(
State(services): State<crate::State>, body: Ruma<delete_timezone_key::unstable::Request>,
) -> Result<delete_timezone_key::unstable::Response> {
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
if *sender_user != body.user_id && body.appservice_info.is_none() {
return Err!(Request(Forbidden("You cannot update the profile of another user")));
}
services.users.set_timezone(&body.user_id, None).await?;
if services.globals.allow_local_presence() {
// Presence update
services
.presence
.ping_presence(&body.user_id, &PresenceState::Online)?;
}
Ok(delete_timezone_key::unstable::Response {})
}
/// # `PUT /_matrix/client/unstable/uk.tcpip.msc4133/profile/:user_id/us.cloke.msc4175.tz`
///
/// Updates the `tz` (timezone) of a user, as per MSC4133 and MSC4175.
///
/// - Also makes sure other users receive the update using presence EDUs
pub(crate) async fn set_timezone_key_route(
State(services): State<crate::State>, body: Ruma<set_timezone_key::unstable::Request>,
) -> Result<set_timezone_key::unstable::Response> {
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
if *sender_user != body.user_id && body.appservice_info.is_none() {
return Err!(Request(Forbidden("You cannot update the profile of another user")));
}
services
.users
.set_timezone(&body.user_id, body.tz.clone())
.await?;
if services.globals.allow_local_presence() {
// Presence update
services
.presence
.ping_presence(&body.user_id, &PresenceState::Online)?;
}
Ok(set_timezone_key::unstable::Response {})
}
/// # `GET /_matrix/client/unstable/uk.tcpip.msc4133/profile/:user_id/us.cloke.msc4175.tz`
///
/// Returns the `timezone` of the user as per MSC4133 and MSC4175.
///
/// - If user is on another server and we do not have a local copy already fetch
/// `timezone` over federation
pub(crate) async fn get_timezone_key_route(
State(services): State<crate::State>, body: Ruma<get_timezone_key::unstable::Request>,
) -> Result<get_timezone_key::unstable::Response> {
if !services.globals.user_is_local(&body.user_id) {
// Create and update our local copy of the user
if let Ok(response) = services
.sending
.send_federation_request(
body.user_id.server_name(),
federation::query::get_profile_information::v1::Request {
user_id: body.user_id.clone(),
field: None, // we want the full user's profile to update locally as well
},
)
.await
{
if !services.users.exists(&body.user_id)? {
services.users.create(&body.user_id, None)?;
}
services
.users
.set_displayname(&body.user_id, response.displayname.clone())
.await?;
services
.users
.set_avatar_url(&body.user_id, response.avatar_url.clone())
.await?;
services
.users
.set_blurhash(&body.user_id, response.blurhash.clone())
.await?;
services
.users
.set_timezone(&body.user_id, response.tz.clone())
.await?;
return Ok(get_timezone_key::unstable::Response {
tz: response.tz,
});
}
}
if !services.users.exists(&body.user_id)? {
// Return 404 if this user doesn't exist and we couldn't fetch it over
// federation
return Err(Error::BadRequest(ErrorKind::NotFound, "Profile was not found."));
}
Ok(get_timezone_key::unstable::Response {
tz: services.users.timezone(&body.user_id)?,
})
}

View file

@ -22,6 +22,9 @@ use crate::{client, server};
pub fn build(router: Router<State>, server: &Server) -> Router<State> {
let config = &server.config;
let mut router = router
.ruma_route(client::get_timezone_key_route)
.ruma_route(client::set_timezone_key_route)
.ruma_route(client::delete_timezone_key_route)
.ruma_route(client::appservice_ping)
.ruma_route(client::get_supported_versions_route)
.ruma_route(client::get_register_available_route)

View file

@ -75,6 +75,7 @@ pub(crate) async fn get_profile_information_route(
let mut displayname = None;
let mut avatar_url = None;
let mut blurhash = None;
let mut tz = None;
match &body.field {
Some(ProfileField::DisplayName) => {
@ -90,6 +91,7 @@ pub(crate) async fn get_profile_information_route(
displayname = services.users.displayname(&body.user_id)?;
avatar_url = services.users.avatar_url(&body.user_id)?;
blurhash = services.users.blurhash(&body.user_id)?;
tz = services.users.timezone(&body.user_id)?;
},
}
@ -97,5 +99,6 @@ pub(crate) async fn get_profile_information_route(
displayname,
avatar_url,
blurhash,
tz,
})
}