matrix-rust-sdk icon indicating copy to clipboard operation
matrix-rust-sdk copied to clipboard

Synapse Admin API

Open stoically opened this issue 1 year ago • 7 comments

Is your feature request related to a problem? Please describe. I found myself implementing a synapse admin struct based on the synapse-admin-api crate types, that allows me to do admin API requests, a second time already in private projects.

Describe the solution you'd like I feel like that synapse admin API requests could be a good fit for the Client, behind a feature gate such as synapse-admin.

Describe alternatives you've considered I could publish my own crate, but keeping up with the fast moving ruma/sdk ecosystem can be challenging.

Notes

Just because I found it mildly tricky, I leave the code to do a shared secret registration here

Requires https://github.com/ruma/synapse-admin-api/pull/15


impl Synapse {
    pub fn new(config: Config) -> Self {
        Self { config }
    }

    pub async fn register_with_shared_secret(
        &self,
    ) -> Result<synapse_admin_api::register_users::shared_secret_register::v1::Response> {
        let reqwest_client = reqwest::Client::builder().build()?;

        let url = self.config.matrix.url.join("/_synapse/admin/v1/register")?;

        let synapse_admin_api::register_users::shared_secret_register_nonce::v1::Response {
            nonce,
            ..
        } = reqwest_client.get(url.clone()).send().await?.json().await?;

        let username = self.config.matrix.user_id.localpart();
        let admin = true;

        let mut mac =
            HmacSha1::new_from_slice(self.config.synapse.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(self.config.matrix.password.as_bytes());
        mac.update(b"\x00");
        mac.update(
            {
                if admin {
                    "admin"
                } else {
                    "notadmin"
                }
            }
            .as_bytes(),
        );
        let mac = mac.finalize();
        let mac = hex::encode(mac.into_bytes());

        let request = synapse_admin_api::register_users::shared_secret_register::v1::Request::new(
            &nonce,
            username,
            &self.config.matrix.displayname,
            &self.config.matrix.password,
            admin,
            &mac,
        );

        let response = reqwest_client
            .post(url)
            .json(&request)
            .send()
            .await?
            .json()
            .await?;

        Ok(response)
    }
}

stoically avatar Aug 05 '22 23:08 stoically

You can already use matrix_sdk::Client::send to send requests from the synapse-admin-api crate, that should reduce the complexity of your example. Most admin API endpoints probably don't require much extra functionality, and I think the mac calculation you have in your example should probably live in some other crate (possibly in synapse-admin-api, actually).

jplatte avatar Aug 10 '22 08:08 jplatte

Generally that sounds very good. I still think that it might be worth to have an explicit feature for synapse admin API, especially if the implementation of it will be low-maintenance for the SDK and high-value for consumers. Another positive side-effect would be that the synapse-admin-api crate would move into the maintenance scope as dependency of the SDK.

I'd be happy to PR the MAC calculation to synapse-admin-api. Where (and how) in the crate would you see that?

stoically avatar Aug 12 '22 11:08 stoically

Another positive side-effect would be that the synapse-admin-api crate would move into the maintenance scope as dependency of the SDK.

Had to smirk when reading this. I would say from the team's perspective this would be a decently-sized downsize if we were to consider that crate our duty to maintain.

I'd be happy to PR the MAC calculation to synapse-admin-api. Where (and how) in the crate would you see that?

I think register_users::shared_secret_register::v1 would be a fine place. How: Just a helper function that returns the hmac String. Probably best behind a feature flag like hmac so users that don't want this functionality don't pay the compile cost for the extra dependencies.

jplatte avatar Aug 12 '22 12:08 jplatte

Had to smirk when reading this. I would say from the team's perspective this would be a decently-sized downsize if we were to consider that crate our duty to maintain.

Hehe, yeah, that's true. I guess that's the general question of whether there's enough potential benefit to consider maintaining a synapse admin api feature. For me personally, out of experience in private and business projects, there was always the point where some synapse admin API call was needed, and the kinds of ways it was done varied wildly - also because the knowledge of how to properly use it in the scope of SDK & ruma isn't that easy to look up for people that are not too deep in the ecosystem. So having some of the API endpoints directly on the client would make it more discoverable as well, maybe.

Just a helper function that returns the hmac String

Sounds good. Will do.

stoically avatar Aug 12 '22 12:08 stoically

the knowledge of how to properly use it in the scope of SDK & ruma isn't that easy to look up for people that are not too deep in the ecosystem. So having some of the API endpoints directly on the client would make it more discoverable as well, maybe.

We could also just add an example though, much easier 😉

jplatte avatar Aug 12 '22 12:08 jplatte

We just discussed this in the team. We won't be spending time on it ourselves, but we'd be happy to review a PR to add a new crate, similar to how we already have a separate appservice crate.

jplatte avatar Aug 18 '22 12:08 jplatte

Side note: This crate may live in the lab/ root first, so that we are a little bit more free to experiment.

Hywan avatar Aug 22 '22 06:08 Hywan

The team got downsized and we can't take on such a crate. Of course happy to provide some help and guidance how to use the SDK to build such a crate.

poljar avatar Feb 02 '24 13:02 poljar