#[cfg(feature = "shared-secret-registration-mac")]
use hmac::{Hmac, Mac, digest::InvalidLength};
use ruma::{
OwnedDeviceId, OwnedServerName, OwnedUserId,
api::{auth_scheme::NoAuthentication, metadata, request, response},
};
#[cfg(feature = "shared-secret-registration-mac")]
use sha1::Sha1;
#[cfg(feature = "shared-secret-registration-mac")]
type HmacSha1 = Hmac<Sha1>;
metadata! {
method: POST,
rate_limited: false,
authentication: NoAuthentication,
path: "/_synapse/admin/v1/register",
}
#[request]
#[derive(Default)]
pub struct Request {
pub nonce: String,
pub username: String,
pub displayname: String,
pub password: String,
pub admin: bool,
pub mac: String,
}
#[response]
pub struct Response {
pub access_token: String,
pub user_id: OwnedUserId,
pub home_server: OwnedServerName,
pub device_id: OwnedDeviceId,
}
impl Request {
pub fn new(
nonce: String,
username: String,
displayname: String,
password: String,
admin: bool,
mac: String,
) -> Self {
Self { nonce, username, displayname, password, admin, mac }
}
}
impl Response {
pub fn new(
access_token: String,
user_id: OwnedUserId,
home_server: OwnedServerName,
device_id: OwnedDeviceId,
) -> Self {
Self { access_token, user_id, home_server, device_id }
}
}
#[cfg(feature = "shared-secret-registration-mac")]
pub fn hmac(
registration_shared_secret: &str,
nonce: &str,
username: &str,
password: &str,
admin: bool,
) -> Result<String, InvalidLength> {
let mut mac = HmacSha1::new_from_slice(registration_shared_secret.as_bytes())?;
mac.update(nonce.as_bytes());
mac.update(b"\x00");
mac.update(username.as_bytes());
mac.update(b"\x00");
mac.update(password.as_bytes());
mac.update(b"\x00");
mac.update(if admin { b"admin" } else { b"notadmin" });
let mac = mac.finalize();
let mac = hex::encode(mac.into_bytes());
Ok(mac)
}