ruma_client_api/profile/
set_profile_field.rs1pub mod v3 {
6 use ruma_common::{
11 api::{response, Metadata},
12 metadata, OwnedUserId,
13 };
14
15 use crate::profile::{profile_field_serde::ProfileFieldValueVisitor, ProfileFieldValue};
16
17 const METADATA: Metadata = metadata! {
18 method: PUT,
19 rate_limited: true,
20 authentication: AccessToken,
21 history: {
22 unstable("uk.tcpip.msc4133") => "/_matrix/client/unstable/uk.tcpip.msc4133/profile/{user_id}/{field}",
23 }
25 };
26
27 #[derive(Debug, Clone)]
29 #[cfg_attr(not(ruma_unstable_exhaustive_types), non_exhaustive)]
30 pub struct Request {
31 pub user_id: OwnedUserId,
33
34 pub value: ProfileFieldValue,
36 }
37
38 impl Request {
39 pub fn new(user_id: OwnedUserId, value: ProfileFieldValue) -> Self {
41 Self { user_id, value }
42 }
43 }
44
45 #[cfg(feature = "client")]
46 impl ruma_common::api::OutgoingRequest for Request {
47 type EndpointError = crate::Error;
48 type IncomingResponse = Response;
49
50 const METADATA: Metadata = METADATA;
51
52 fn try_into_http_request<T: Default + bytes::BufMut>(
53 self,
54 base_url: &str,
55 _access_token: ruma_common::api::SendAccessToken<'_>,
56 considering: &'_ ruma_common::api::SupportedVersions,
57 ) -> Result<http::Request<T>, ruma_common::api::error::IntoHttpError> {
58 let url = METADATA.make_endpoint_url(
59 considering,
60 base_url,
61 &[&self.user_id, &self.value.field_name()],
62 "",
63 )?;
64
65 let http_request = http::Request::builder()
66 .method(METADATA.method)
67 .uri(url)
68 .body(ruma_common::serde::json_to_buf(&self.value)?)
69 .unwrap();
72
73 Ok(http_request)
74 }
75 }
76
77 #[cfg(feature = "server")]
78 impl ruma_common::api::IncomingRequest for Request {
79 type EndpointError = crate::Error;
80 type OutgoingResponse = Response;
81
82 const METADATA: Metadata = METADATA;
83
84 fn try_from_http_request<B, S>(
85 request: http::Request<B>,
86 path_args: &[S],
87 ) -> Result<Self, ruma_common::api::error::FromHttpRequestError>
88 where
89 B: AsRef<[u8]>,
90 S: AsRef<str>,
91 {
92 use serde::de::{Deserializer, Error as _};
93
94 use crate::profile::ProfileFieldName;
95
96 let (user_id, field): (OwnedUserId, ProfileFieldName) =
97 serde::Deserialize::deserialize(serde::de::value::SeqDeserializer::<
98 _,
99 serde::de::value::Error,
100 >::new(
101 path_args.iter().map(::std::convert::AsRef::as_ref),
102 ))?;
103
104 let value = serde_json::Deserializer::from_slice(request.body().as_ref())
105 .deserialize_map(ProfileFieldValueVisitor(Some(field.clone())))?
106 .ok_or_else(|| serde_json::Error::custom(format!("missing field `{field}`")))?;
107
108 Ok(Request { user_id, value })
109 }
110 }
111
112 #[response(error = crate::Error)]
114 #[derive(Default)]
115 pub struct Response {}
116
117 impl Response {
118 pub fn new() -> Self {
120 Self {}
121 }
122 }
123}
124
125#[cfg(test)]
126mod tests {
127 use assert_matches2::assert_matches;
128 use ruma_common::{owned_mxc_uri, owned_user_id};
129 use serde_json::{
130 from_slice as from_json_slice, json, to_vec as to_json_vec, Value as JsonValue,
131 };
132
133 use super::v3::Request;
134 use crate::profile::ProfileFieldValue;
135
136 #[test]
137 #[cfg(feature = "client")]
138 fn serialize_request() {
139 use ruma_common::api::{OutgoingRequest, SendAccessToken, SupportedVersions};
140
141 let request = Request::new(
142 owned_user_id!("@alice:localhost"),
143 ProfileFieldValue::AvatarUrl(owned_mxc_uri!("mxc://localhost/abcdef")),
144 );
145
146 let http_request = request
147 .try_into_http_request::<Vec<u8>>(
148 "http://localhost/",
149 SendAccessToken::Always("access_token"),
150 &SupportedVersions::from_parts(&["v11".to_owned()], &Default::default()),
151 )
152 .unwrap();
153
154 assert_eq!(
155 http_request.uri().path(),
156 "/_matrix/client/unstable/uk.tcpip.msc4133/profile/@alice:localhost/avatar_url"
157 );
158 assert_eq!(
159 from_json_slice::<JsonValue>(http_request.body().as_ref()).unwrap(),
160 json!({
161 "avatar_url": "mxc://localhost/abcdef",
162 })
163 );
164 }
165
166 #[test]
167 #[cfg(feature = "server")]
168 fn deserialize_request_valid_field() {
169 use ruma_common::api::IncomingRequest;
170
171 let body = to_json_vec(&json!({
172 "displayname": "Alice",
173 }))
174 .unwrap();
175
176 let request = Request::try_from_http_request(
177 http::Request::put("http://localhost/_matrix/client/unstable/uk.tcpip.msc4133/profile/@alice:localhost/displayname").body(body).unwrap(),
178 &["@alice:localhost", "displayname"],
179 ).unwrap();
180
181 assert_eq!(request.user_id, "@alice:localhost");
182 assert_matches!(request.value, ProfileFieldValue::DisplayName(display_name));
183 assert_eq!(display_name, "Alice");
184 }
185
186 #[test]
187 #[cfg(feature = "server")]
188 fn deserialize_request_invalid_field() {
189 use ruma_common::api::IncomingRequest;
190
191 let body = to_json_vec(&json!({
192 "custom_field": "value",
193 }))
194 .unwrap();
195
196 Request::try_from_http_request(
197 http::Request::put("http://localhost/_matrix/client/unstable/uk.tcpip.msc4133/profile/@alice:localhost/displayname").body(body).unwrap(),
198 &["@alice:localhost", "displayname"],
199 ).unwrap_err();
200 }
201}