babelforce-manager-sdk 0.44.0

Rust SDK for the babelforce manager APIs — auth, user & agent management, call reporting, metrics, and task automations.
Documentation
use crate::error::{map_manager_err, ManagerError};
use crate::gen::manager::apis::configuration::Configuration;
use crate::gen::manager::apis::manager_api;
use crate::gen::manager::apis::user_management_api as api;
use crate::gen::manager::models;
use crate::resources::raw::get_json;
use crate::retry::{with_retry, RetryPolicy};
use crate::token::SharedCfg;

/// Optional server-side filters for [`UsersResource::list`].
#[derive(Debug, Clone, Default)]
pub struct ListUsersQuery {
    /// Only return the user(s) with this email address (the endpoint's `?email=` filter).
    pub email: Option<String>,
}

/// User management — `/api/v2/users`.
pub struct UsersResource {
    pub(crate) cfg: SharedCfg<Configuration>,
    pub(crate) retry: RetryPolicy,
}

impl UsersResource {
    /// Get the currently authenticated user.
    ///
    /// The underlying generated operation is marked deprecated upstream, but it remains part of the
    /// spec and is wrapped here for parity with the TypeScript/Go SDKs.
    #[allow(deprecated)]
    pub async fn me(&self) -> Result<models::GenericItemResponse, ManagerError> {
        let cfg = self.cfg.get().await?;
        let cfg = cfg.as_ref();
        with_retry(&self.retry, true, || manager_api::get_me(cfg))
            .await
            .map_err(map_manager_err)
    }

    /// Get a user by email.
    pub async fn get_by_email(
        &self,
        email: &str,
    ) -> Result<models::ManagedUserItemResponse, ManagerError> {
        let cfg = self.cfg.get().await?;
        let cfg = cfg.as_ref();
        with_retry(&self.retry, true, || {
            manager_api::get_user_by_email(cfg, email)
        })
        .await
        .map_err(map_manager_err)
    }

    /// List users, optionally filtered server-side.
    ///
    /// The endpoint exposes no pagination parameters — a single fetch returns all matches.
    ///
    /// Stands in for the generated `list_users`, whose `email` parameter (an anyOf
    /// string-or-array type) is JSON-serialized into the query — it would send
    /// `?email="a@example.com"` with literal quotes, which the server does not match. The facade
    /// builds the query itself and decodes into the same generated response model.
    pub async fn list(
        &self,
        query: ListUsersQuery,
    ) -> Result<Vec<models::ManagedUser>, ManagerError> {
        let cfg = self.cfg.get().await?;
        let cfg = cfg.as_ref();
        let mut path = "/api/v2/users".to_string();
        if let Some(email) = &query.email {
            path.push_str(&format!(
                "?email={}",
                crate::gen::manager::apis::urlencode(email)
            ));
        }
        let resp: models::PaginatedManagedUserResponse = with_retry(&self.retry, true, || async {
            let v = get_json(cfg, &path).await?;
            serde_json::from_value(v).map_err(|e| ManagerError::Decode(e.to_string()))
        })
        .await?;
        Ok(resp.items)
    }

    /// List all users (unfiltered — the endpoint exposes no pagination parameters).
    pub async fn list_all(&self) -> Result<Vec<models::ManagedUser>, ManagerError> {
        self.list(ListUsersQuery::default()).await
    }

    /// Create a user.
    pub async fn create(
        &self,
        user: models::CreateManagedUserRequest,
    ) -> Result<models::ManagedUserItemResponse, ManagerError> {
        let cfg = self.cfg.get().await?;
        let cfg = cfg.as_ref();
        with_retry(&self.retry, false, || {
            api::create_user(cfg, Some(user.clone()))
        })
        .await
        .map_err(map_manager_err)
    }

    /// Enable the given users (by email).
    pub async fn enable(&self, emails: Vec<String>) -> Result<(), ManagerError> {
        let cfg = self.cfg.get().await?;
        let cfg = cfg.as_ref();
        with_retry(&self.retry, false, || {
            api::enable_users(cfg, Some(email_list(&emails)))
        })
        .await
        .map_err(map_manager_err)?;
        Ok(())
    }

    /// Disable the given users (by email).
    pub async fn disable(&self, emails: Vec<String>) -> Result<(), ManagerError> {
        let cfg = self.cfg.get().await?;
        let cfg = cfg.as_ref();
        with_retry(&self.retry, false, || {
            api::disable_users(cfg, Some(email_list(&emails)))
        })
        .await
        .map_err(map_manager_err)?;
        Ok(())
    }

    /// Delete the given users (by email).
    pub async fn delete(&self, emails: Vec<String>) -> Result<(), ManagerError> {
        let cfg = self.cfg.get().await?;
        let cfg = cfg.as_ref();
        with_retry(&self.retry, false, || {
            api::delete_users(cfg, Some(email_list(&emails)))
        })
        .await
        .map_err(map_manager_err)?;
        Ok(())
    }

    /// Trigger a password-reset email for the given users (by email).
    pub async fn reset_passwords(&self, emails: Vec<String>) -> Result<(), ManagerError> {
        let cfg = self.cfg.get().await?;
        let cfg = cfg.as_ref();
        with_retry(&self.retry, false, || {
            api::reset_passwords(cfg, Some(email_list(&emails)))
        })
        .await
        .map_err(map_manager_err)?;
        Ok(())
    }

    /// List the role names that can be assigned to users.
    pub async fn list_roles(&self) -> Result<Vec<models::AccountRole>, ManagerError> {
        let cfg = self.cfg.get().await?;
        let cfg = cfg.as_ref();
        let resp = with_retry(&self.retry, true, || api::list_available_roles(cfg))
            .await
            .map_err(map_manager_err)?;
        Ok(resp.items)
    }

    /// Grant the given roles to the given users (by email).
    pub async fn add_roles(
        &self,
        emails: Vec<String>,
        roles: Vec<models::AccountRole>,
    ) -> Result<(), ManagerError> {
        let cfg = self.cfg.get().await?;
        let cfg = cfg.as_ref();
        with_retry(&self.retry, false, || {
            api::add_roles(cfg, Some(role_binding(&emails, &roles)))
        })
        .await
        .map_err(map_manager_err)?;
        Ok(())
    }

    /// Revoke the given roles from the given users (by email).
    pub async fn remove_roles(
        &self,
        emails: Vec<String>,
        roles: Vec<models::AccountRole>,
    ) -> Result<(), ManagerError> {
        let cfg = self.cfg.get().await?;
        let cfg = cfg.as_ref();
        with_retry(&self.retry, false, || {
            api::remove_roles(cfg, Some(role_binding(&emails, &roles)))
        })
        .await
        .map_err(map_manager_err)?;
        Ok(())
    }
}

fn email_list(emails: &[String]) -> models::EmailListRequest {
    models::EmailListRequest {
        emails: emails.to_vec(),
    }
}

fn role_binding(emails: &[String], roles: &[models::AccountRole]) -> models::EmailRoleBinding {
    models::EmailRoleBinding {
        emails: Some(emails.to_vec()),
        roles: Some(roles.to_vec()),
    }
}