synapse_admin_api/register_users/shared_secret_register/
v1.rs

1//! [POST /_synapse/admin/v1/register](https://github.com/element-hq/synapse/blob/master/docs/admin_api/register_api.md)
2
3#[cfg(feature = "shared-secret-registration-mac")]
4use hmac::{Hmac, Mac, digest::InvalidLength};
5use ruma::{
6    OwnedDeviceId, OwnedServerName, OwnedUserId,
7    api::{auth_scheme::NoAuthentication, metadata, request, response},
8};
9#[cfg(feature = "shared-secret-registration-mac")]
10use sha1::Sha1;
11
12#[cfg(feature = "shared-secret-registration-mac")]
13type HmacSha1 = Hmac<Sha1>;
14
15metadata! {
16    method: POST,
17    rate_limited: false,
18    authentication: NoAuthentication,
19    path: "/_synapse/admin/v1/register",
20}
21
22#[request]
23#[derive(Default)]
24pub struct Request {
25    /// The nonce retrieved from the nonce endpoint.
26    pub nonce: String,
27
28    /// Localpart for the account.
29    pub username: String,
30
31    /// Display name for the account.
32    pub displayname: String,
33
34    /// Password for the account.
35    pub password: String,
36
37    /// Whether the account should be an admin.
38    pub admin: bool,
39
40    /// The MAC is the hex digest output of the HMAC-SHA1 algorithm, with
41    /// the key being the shared secret and the content being the nonce,
42    /// user, password, either the string "admin" or "notadmin", and
43    /// optionally the user_type each separated by NULs.
44    pub mac: String,
45}
46
47#[response]
48pub struct Response {
49    /// Access token.
50    pub access_token: String,
51
52    /// Registered user id.
53    pub user_id: OwnedUserId,
54
55    /// Homeserver name.
56    pub home_server: OwnedServerName,
57
58    /// Device ID.
59    pub device_id: OwnedDeviceId,
60}
61
62impl Request {
63    /// Creates a `Request` with the given data.
64    pub fn new(
65        nonce: String,
66        username: String,
67        displayname: String,
68        password: String,
69        admin: bool,
70        mac: String,
71    ) -> Self {
72        Self { nonce, username, displayname, password, admin, mac }
73    }
74}
75
76impl Response {
77    /// Creates a `Response` with the given data.
78    pub fn new(
79        access_token: String,
80        user_id: OwnedUserId,
81        home_server: OwnedServerName,
82        device_id: OwnedDeviceId,
83    ) -> Self {
84        Self { access_token, user_id, home_server, device_id }
85    }
86}
87
88/// Calculate the MAC based on the given inputs.
89///
90/// See <https://github.com/element-hq/synapse/blob/master/docs/admin_api/register_api.md> for details.
91#[cfg(feature = "shared-secret-registration-mac")]
92pub fn hmac(
93    registration_shared_secret: &str,
94    nonce: &str,
95    username: &str,
96    password: &str,
97    admin: bool,
98) -> Result<String, InvalidLength> {
99    let mut mac = HmacSha1::new_from_slice(registration_shared_secret.as_bytes())?;
100    mac.update(nonce.as_bytes());
101    mac.update(b"\x00");
102    mac.update(username.as_bytes());
103    mac.update(b"\x00");
104    mac.update(password.as_bytes());
105    mac.update(b"\x00");
106    mac.update(if admin { b"admin" } else { b"notadmin" });
107    let mac = mac.finalize();
108    let mac = hex::encode(mac.into_bytes());
109
110    Ok(mac)
111}