ruma_appservice_api/lib.rs
1#![doc(html_favicon_url = "https://ruma.dev/favicon.ico")]
2#![doc(html_logo_url = "https://ruma.dev/images/logo.png")]
3//! (De)serializable types for the [Matrix Application Service API][appservice-api].
4//! These types can be shared by application service and server code.
5//!
6//! [appservice-api]: https://spec.matrix.org/v1.19/application-service-api/
7
8// This crate is not useful without either of those features, so export nothing if they are not
9// enabled to avoid errors when running checks wrongly without enabling any of them.
10#![cfg(any(feature = "client", feature = "server"))]
11#![warn(missing_docs)]
12
13use ruma_common::api::auth_scheme::{
14 AuthScheme, ExtractTokenError, add_access_token_as_authorization_header,
15 extract_bearer_or_query_token,
16};
17use serde::{Deserialize, Serialize};
18
19pub mod event;
20#[cfg(feature = "unstable-msc4417")]
21pub mod media;
22pub mod ping;
23pub mod query;
24pub mod thirdparty;
25
26/// A namespace defined by an application service.
27///
28/// Used for [appservice registration](https://spec.matrix.org/v1.19/application-service-api/#registration).
29#[derive(Clone, Debug, Serialize, Deserialize)]
30#[cfg_attr(not(ruma_unstable_exhaustive_types), non_exhaustive)]
31pub struct Namespace {
32 /// Whether this application service has exclusive access to events within this namespace.
33 pub exclusive: bool,
34
35 /// A POSIX regular expression defining which values this namespace includes.
36 pub regex: String,
37}
38
39impl Namespace {
40 /// Creates a new `Namespace` with the given exclusivity and regex pattern.
41 pub fn new(exclusive: bool, regex: String) -> Self {
42 Namespace { exclusive, regex }
43 }
44}
45
46/// Namespaces defined by an application service.
47///
48/// Used for [appservice registration](https://spec.matrix.org/v1.19/application-service-api/#registration).
49#[derive(Clone, Debug, Default, Serialize, Deserialize)]
50#[cfg_attr(not(ruma_unstable_exhaustive_types), non_exhaustive)]
51pub struct Namespaces {
52 /// Events which are sent from certain users.
53 #[serde(default, skip_serializing_if = "Vec::is_empty")]
54 pub users: Vec<Namespace>,
55
56 /// Events which are sent in rooms with certain room aliases.
57 #[serde(default, skip_serializing_if = "Vec::is_empty")]
58 pub aliases: Vec<Namespace>,
59
60 /// Events which are sent in rooms with certain room IDs.
61 #[serde(default, skip_serializing_if = "Vec::is_empty")]
62 pub rooms: Vec<Namespace>,
63
64 /// URLs that this appservice will be queried about.
65 #[cfg(feature = "unstable-msc4417")]
66 #[serde(default, skip_serializing_if = "Vec::is_empty")]
67 #[serde(rename = "uk.half-shot.msc4417.preview_urls")]
68 pub preview_urls: Vec<Namespace>,
69}
70
71impl Namespaces {
72 /// Creates a new `Namespaces` instance with empty namespaces for `users`, `aliases` and
73 /// `rooms` (none of them are explicitly required)
74 pub fn new() -> Self {
75 Self::default()
76 }
77}
78
79/// Information required in the registration yaml file that a homeserver needs.
80///
81/// To create an instance of this type, first create a `RegistrationInit` and convert it via
82/// `Registration::from` / `.into()`.
83///
84/// Used for [appservice registration](https://spec.matrix.org/v1.19/application-service-api/#registration).
85#[derive(Clone, Debug, Serialize, Deserialize)]
86#[cfg_attr(not(ruma_unstable_exhaustive_types), non_exhaustive)]
87pub struct Registration {
88 /// A unique, user - defined ID of the application service which will never change.
89 pub id: String,
90
91 /// The URL for the application service.
92 ///
93 /// Optionally set to `null` if no traffic is required.
94 #[serde(deserialize_with = "Option::deserialize")]
95 pub url: Option<String>,
96
97 /// A unique token for application services to use to authenticate requests to Homeservers.
98 pub as_token: String,
99
100 /// A unique token for Homeservers to use to authenticate requests to application services.
101 pub hs_token: String,
102
103 /// The localpart of the user associated with the application service.
104 pub sender_localpart: String,
105
106 /// A list of users, aliases and rooms namespaces that the application service controls.
107 pub namespaces: Namespaces,
108
109 /// Whether requests from masqueraded users are rate-limited.
110 ///
111 /// The sender is excluded.
112 #[serde(skip_serializing_if = "Option::is_none")]
113 pub rate_limited: Option<bool>,
114
115 /// The external protocols which the application service provides (e.g. IRC).
116 #[serde(skip_serializing_if = "Option::is_none")]
117 pub protocols: Option<Vec<String>>,
118
119 /// Whether the application service wants to receive ephemeral data.
120 ///
121 /// Defaults to `false`.
122 #[serde(default, skip_serializing_if = "ruma_common::serde::is_default")]
123 pub receive_ephemeral: bool,
124}
125
126/// Initial set of fields of `Registration`.
127///
128/// This struct will not be updated even if additional fields are added to `Registration` in a new
129/// (non-breaking) release of the Matrix specification.
130///
131/// Used for [appservice registration](https://spec.matrix.org/v1.19/application-service-api/#registration).
132#[derive(Debug)]
133#[allow(clippy::exhaustive_structs)]
134pub struct RegistrationInit {
135 /// A unique, user - defined ID of the application service which will never change.
136 pub id: String,
137
138 /// The URL for the application service.
139 ///
140 /// Optionally set to `null` if no traffic is required.
141 pub url: Option<String>,
142
143 /// A unique token for application services to use to authenticate requests to Homeservers.
144 pub as_token: String,
145
146 /// A unique token for Homeservers to use to authenticate requests to application services.
147 pub hs_token: String,
148
149 /// The localpart of the user associated with the application service.
150 pub sender_localpart: String,
151
152 /// A list of users, aliases and rooms namespaces that the application service controls.
153 pub namespaces: Namespaces,
154
155 /// Whether requests from masqueraded users are rate-limited.
156 ///
157 /// The sender is excluded.
158 pub rate_limited: Option<bool>,
159
160 /// The external protocols which the application service provides (e.g. IRC).
161 pub protocols: Option<Vec<String>>,
162}
163
164impl From<RegistrationInit> for Registration {
165 fn from(init: RegistrationInit) -> Self {
166 let RegistrationInit {
167 id,
168 url,
169 as_token,
170 hs_token,
171 sender_localpart,
172 namespaces,
173 rate_limited,
174 protocols,
175 } = init;
176 Self {
177 id,
178 url,
179 as_token,
180 hs_token,
181 sender_localpart,
182 namespaces,
183 rate_limited,
184 protocols,
185 receive_ephemeral: false,
186 }
187 }
188}
189
190/// Authentication is required, and can only be performed by a homeserver sending a request to an
191/// appservice, by including a homeserver access token in the `Authorization` http header, or an
192/// `access_token` query parameter.
193///
194/// Using the query parameter is deprecated since Matrix 1.4.
195#[derive(Debug, Clone, Copy, Default)]
196#[allow(clippy::exhaustive_structs)]
197pub struct HomeserverToken;
198
199impl AuthScheme for HomeserverToken {
200 type Input<'a> = &'a str;
201 type AddAuthenticationError = http::header::InvalidHeaderValue;
202 /// The homeserver token.
203 type Output = String;
204 type ExtractAuthenticationError = ExtractTokenError;
205
206 fn add_authentication<T: AsRef<[u8]>>(
207 request: &mut http::Request<T>,
208 access_token: Self::Input<'_>,
209 ) -> Result<(), Self::AddAuthenticationError> {
210 add_access_token_as_authorization_header(request.headers_mut(), access_token)
211 }
212
213 fn extract_authentication<T>(
214 request: &http::Request<T>,
215 ) -> Result<Self::Output, Self::ExtractAuthenticationError> {
216 extract_bearer_or_query_token(request)?.ok_or(ExtractTokenError::MissingAccessToken)
217 }
218}