uptrakit-openapi-client 0.0.3

Typed HTTP client for the Uptrakit web API
Documentation
use crate::Result;
use crate::UptrakitClient;
use crate::types_impl::server_cert::RenewServerCertResponse;
use crate::types_impl::settings_access::{AccessSettingsResponse, UpdateAccessSettingsRequest};
use crate::types_impl::settings_agent_certs::{
    AgentCertificateSettingsResponse, UpdateAgentCertificateSettingsRequest,
};
use crate::types_impl::settings_ca::RotateCaResponse;
use crate::types_impl::settings_combined::{
    CombinedSettingsResponse, GlobalSettingsCombinedResponse,
};
use crate::types_impl::settings_network::{NetworkSettingsResponse, UpdateNetworkSettingsRequest};
use crate::types_impl::settings_reset::{ResetDataRequest, ResetDataResponse};

impl UptrakitClient {
    /// Get combined global settings (network, system services, MQTT limit, optional NATS).
    pub async fn get_global_combined_settings(&self) -> Result<GlobalSettingsCombinedResponse> {
        self.get(crate::paths::global_settings::COMBINED).await
    }

    /// Get combined settings (access, certificates, enrollment tokens).
    pub async fn get_combined_settings(&self) -> Result<CombinedSettingsResponse> {
        self.get(crate::paths::settings::COMBINED).await
    }

    /// Get access settings (registration + authentication combined).
    /// Returns the response body and the raw `ETag` header value.
    pub async fn get_access_settings(&self) -> Result<(AccessSettingsResponse, String)> {
        self.get_with_etag(crate::paths::settings::ACCESS).await
    }

    /// Update access settings.  `etag` must be the value returned by a prior
    /// `get_access_settings` call — the server requires `If-Match` for optimistic locking.
    pub async fn update_access_settings(
        &self,
        req: &UpdateAccessSettingsRequest,
        etag: &str,
    ) -> Result<(AccessSettingsResponse, String)> {
        self.put_json_with_etag(crate::paths::settings::ACCESS, req, etag)
            .await
    }

    /// Get agent certificate settings.
    pub async fn get_agent_certificate_settings(&self) -> Result<AgentCertificateSettingsResponse> {
        self.get(crate::paths::settings::AGENT_CERTIFICATES).await
    }

    /// Update agent certificate settings.
    pub async fn update_agent_certificate_settings(
        &self,
        req: &UpdateAgentCertificateSettingsRequest,
    ) -> Result<AgentCertificateSettingsResponse> {
        self.put_json(crate::paths::settings::AGENT_CERTIFICATES, req)
            .await
    }

    /// Get network settings.
    pub async fn get_network_settings(&self) -> Result<NetworkSettingsResponse> {
        self.get(crate::paths::settings::NETWORK).await
    }

    /// Update network settings.
    pub async fn update_network_settings(
        &self,
        req: &UpdateNetworkSettingsRequest,
    ) -> Result<NetworkSettingsResponse> {
        self.put_json(crate::paths::settings::NETWORK, req).await
    }

    /// Rotate the CA certificate.
    pub async fn rotate_ca(&self) -> Result<RotateCaResponse> {
        self.post_empty(crate::paths::settings::ROTATE_CA).await
    }

    /// Renew the server TLS certificate.
    pub async fn renew_server_certificate(&self) -> Result<RenewServerCertResponse> {
        self.post_empty(crate::paths::settings::RENEW_SERVER_CERT)
            .await
    }

    /// Reset all tenant-scoped data.
    pub async fn reset_data(&self, req: &ResetDataRequest) -> Result<ResetDataResponse> {
        self.post_json(crate::paths::settings::RESET_DATA, req)
            .await
    }
}

#[cfg(test)]
mod tests {
    use crate::types_impl::SecretString;
    use crate::types_impl::registration::RegistrationMode;
    use crate::types_impl::settings_access::UpdateAccessSettingsRequest;
    use crate::types_impl::settings_agent_certs::UpdateAgentCertificateSettingsRequest;
    use crate::types_impl::settings_network::UpdateNetworkSettingsRequest;

    #[test]
    fn update_access_settings_serialization() {
        let req = UpdateAccessSettingsRequest {
            mode: RegistrationMode::Invite,
            token: Some(SecretString::new("my-invite-token")),
            require_token_for_oidc: Some(true),
            password_auth_enabled: Some(false),
            two_factor_required: None,
        };
        let json = serde_json::to_value(&req).expect("serialize");
        assert_eq!(json["mode"], "invite");
        assert_eq!(json["token"], "my-invite-token");
        assert_eq!(json["require_token_for_oidc"], true);
        assert_eq!(json["password_auth_enabled"], false);
    }

    #[test]
    fn update_agent_certificate_settings_serialization() {
        let req = UpdateAgentCertificateSettingsRequest {
            lifetime_hours: Some(8_760),
            renewal_window_hours: Some(72),
        };
        let json = serde_json::to_value(&req).expect("serialize");
        assert_eq!(json["lifetime_hours"], 8_760);
        assert_eq!(json["renewal_window_hours"], 72);
    }

    #[test]
    fn update_network_settings_serialization() {
        let req = UpdateNetworkSettingsRequest {
            trusted_proxies: Some(vec!["10.0.0.0/8".to_string()]),
            real_ip_header: Some("X-Real-IP".to_string()),
            sans: None,
            https_addr: None,
            forwarded_client_cert_info_header: None,
            forwarded_client_cert_pem_header: None,
            pki_addr: None,
            regenerate_cert: None,
        };
        let json = serde_json::to_value(&req).expect("serialize");
        assert_eq!(json["trusted_proxies"][0], "10.0.0.0/8");
        assert_eq!(json["real_ip_header"], "X-Real-IP");
    }
}