Skip to main content

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