ruma_client_api/push/
set_pushrule.rs1pub mod v3 {
6 use ruma_common::{
11 api::{auth_scheme::AccessToken, error::Error, response},
12 metadata,
13 push::{Action, NewPushRule, PushCondition},
14 };
15
16 metadata! {
17 method: PUT,
18 rate_limited: true,
19 authentication: AccessToken,
20 history: {
21 1.0 => "/_matrix/client/r0/pushrules/global/{kind}/{rule_id}",
22 1.1 => "/_matrix/client/v3/pushrules/global/{kind}/{rule_id}",
23 }
24 }
25
26 #[derive(Clone, Debug)]
28 #[cfg_attr(not(ruma_unstable_exhaustive_types), non_exhaustive)]
29 pub struct Request {
30 pub rule: NewPushRule,
32
33 pub before: Option<String>,
36
37 pub after: Option<String>,
40 }
41
42 #[response]
44 #[derive(Default)]
45 pub struct Response {}
46
47 impl Request {
48 pub fn new(rule: NewPushRule) -> Self {
50 Self { rule, before: None, after: None }
51 }
52 }
53
54 impl Response {
55 pub fn new() -> Self {
57 Self {}
58 }
59 }
60
61 #[doc(hidden)]
62 #[cfg(feature = "client")]
63 pub struct RequestBody(NewPushRule);
64
65 #[cfg(feature = "client")]
66 impl ruma_common::api::OutgoingBody for RequestBody {
67 type Error = serde_json::Error;
68
69 fn content_type(&self) -> Option<http::HeaderValue> {
70 Some(ruma_common::http_headers::APPLICATION_JSON)
71 }
72
73 fn try_into_buf<T: Default + bytes::BufMut + AsRef<[u8]>>(self) -> serde_json::Result<T> {
74 match self.0 {
75 NewPushRule::Override(r) | NewPushRule::Underride(r) => {
76 let body =
77 ConditionalRequestBody { actions: r.actions, conditions: r.conditions };
78 ruma_common::serde::json_to_buf(&body)
79 }
80 NewPushRule::Content(r) => {
81 let body = PatternedRequestBody { actions: r.actions, pattern: r.pattern };
82 ruma_common::serde::json_to_buf(&body)
83 }
84 NewPushRule::Room(r) => {
85 let body = SimpleRequestBody { actions: r.actions };
86 ruma_common::serde::json_to_buf(&body)
87 }
88 NewPushRule::Sender(r) => {
89 let body = SimpleRequestBody { actions: r.actions };
90 ruma_common::serde::json_to_buf(&body)
91 }
92 #[cfg(not(ruma_unstable_exhaustive_types))]
93 _ => unreachable!("variant added to NewPushRule not serializable to request body"),
94 }
95 }
96 }
97
98 #[cfg(feature = "client")]
99 impl ruma_common::api::OutgoingRequest for Request {
100 type Body = RequestBody;
101 type EndpointError = Error;
102 type IncomingResponse = Response;
103
104 fn try_into_http_request_inner(
105 self,
106 base_url: &str,
107 considering: std::borrow::Cow<'_, ruma_common::api::SupportedVersions>,
108 ) -> Result<http::Request<RequestBody>, ruma_common::api::error::IntoHttpError> {
109 use ruma_common::api::Metadata;
110
111 let query_string = serde_html_form::to_string(RequestQuery {
112 before: self.before,
113 after: self.after,
114 })?;
115
116 let url = Self::make_endpoint_url(
117 considering,
118 base_url,
119 &[&self.rule.kind(), &self.rule.rule_id()],
120 &query_string,
121 )?;
122
123 let http_request = http::Request::builder()
124 .method(Self::METHOD)
125 .uri(url)
126 .body(RequestBody(self.rule))?;
127
128 Ok(http_request)
129 }
130 }
131
132 #[cfg(feature = "server")]
133 impl ruma_common::api::IncomingRequest for Request {
134 type EndpointError = Error;
135 type OutgoingResponse = Response;
136
137 fn try_from_http_request_inner(
138 request: http::Request<&[u8]>,
139 path_args: &[&str],
140 ) -> Result<Self, ruma_common::api::error::DeserializationError> {
141 use ruma_common::push::{
142 NewConditionalPushRule, NewPatternedPushRule, NewSimplePushRule,
143 };
144
145 #[derive(Debug, serde::Deserialize)]
147 #[serde(rename_all = "lowercase")]
148 enum RuleKind {
149 Override,
150 Underride,
151 Sender,
152 Room,
153 Content,
154 }
155
156 let (kind, rule_id): (RuleKind, String) =
157 serde::Deserialize::deserialize(serde::de::value::SeqDeserializer::<
158 _,
159 serde::de::value::Error,
160 >::new(path_args.iter().copied()))?;
161
162 let RequestQuery { before, after } =
163 serde_html_form::from_str(request.uri().query().unwrap_or(""))?;
164
165 let rule = match kind {
166 RuleKind::Override => {
167 let ConditionalRequestBody { actions, conditions } =
168 serde_json::from_slice(request.body())?;
169 NewPushRule::Override(NewConditionalPushRule::new(rule_id, conditions, actions))
170 }
171 RuleKind::Underride => {
172 let ConditionalRequestBody { actions, conditions } =
173 serde_json::from_slice(request.body())?;
174 NewPushRule::Underride(NewConditionalPushRule::new(
175 rule_id, conditions, actions,
176 ))
177 }
178 RuleKind::Sender => {
179 let SimpleRequestBody { actions } = serde_json::from_slice(request.body())?;
180 let rule_id = rule_id.try_into()?;
181 NewPushRule::Sender(NewSimplePushRule::new(rule_id, actions))
182 }
183 RuleKind::Room => {
184 let SimpleRequestBody { actions } = serde_json::from_slice(request.body())?;
185 let rule_id = rule_id.try_into()?;
186 NewPushRule::Room(NewSimplePushRule::new(rule_id, actions))
187 }
188 RuleKind::Content => {
189 let PatternedRequestBody { actions, pattern } =
190 serde_json::from_slice(request.body())?;
191 NewPushRule::Content(NewPatternedPushRule::new(rule_id, pattern, actions))
192 }
193 };
194
195 Ok(Self { rule, before, after })
196 }
197 }
198
199 #[derive(Debug)]
200 #[cfg_attr(feature = "client", derive(serde::Serialize))]
201 #[cfg_attr(feature = "server", derive(serde::Deserialize))]
202 struct RequestQuery {
203 #[serde(skip_serializing_if = "Option::is_none")]
204 before: Option<String>,
205
206 #[serde(skip_serializing_if = "Option::is_none")]
207 after: Option<String>,
208 }
209
210 #[derive(Debug)]
211 #[cfg_attr(feature = "client", derive(serde::Serialize))]
212 #[cfg_attr(feature = "server", derive(serde::Deserialize))]
213 struct SimpleRequestBody {
214 actions: Vec<Action>,
215 }
216
217 #[derive(Debug)]
218 #[cfg_attr(feature = "client", derive(serde::Serialize))]
219 #[cfg_attr(feature = "server", derive(serde::Deserialize))]
220 struct PatternedRequestBody {
221 actions: Vec<Action>,
222
223 pattern: String,
224 }
225
226 #[derive(Debug)]
227 #[cfg_attr(feature = "client", derive(serde::Serialize))]
228 #[cfg_attr(feature = "server", derive(serde::Deserialize))]
229 struct ConditionalRequestBody {
230 actions: Vec<Action>,
231
232 conditions: Vec<PushCondition>,
233 }
234}