Skip to main content

systemprompt_cloud/api_client/
tenant_api.rs

1use anyhow::Result;
2use serde::Serialize;
3use systemprompt_models::modules::ApiPaths;
4
5use super::types::{
6    ApiResponse, CustomDomainResponse, DeployResponse, ExternalDbAccessResponse,
7    ListSecretsResponse, RegistryToken, RotateCredentialsResponse, RotateSyncTokenResponse,
8    SetCustomDomainRequest, SetExternalDbAccessRequest, SetSecretsRequest, StatusResponse,
9    TenantSecrets, TenantStatus,
10};
11use super::CloudApiClient;
12
13#[derive(Serialize)]
14struct DeployRequest {
15    image: String,
16}
17
18impl CloudApiClient {
19    pub async fn get_tenant_status(&self, tenant_id: &str) -> Result<TenantStatus> {
20        let response: ApiResponse<TenantStatus> =
21            self.get(&ApiPaths::tenant_status(tenant_id)).await?;
22        Ok(response.data)
23    }
24
25    pub async fn get_registry_token(&self, tenant_id: &str) -> Result<RegistryToken> {
26        let response: ApiResponse<RegistryToken> = self
27            .get(&ApiPaths::tenant_registry_token(tenant_id))
28            .await?;
29        Ok(response.data)
30    }
31
32    pub async fn deploy(&self, tenant_id: &str, image: &str) -> Result<DeployResponse> {
33        let request = DeployRequest {
34            image: image.to_string(),
35        };
36        let response: ApiResponse<DeployResponse> = self
37            .post(&ApiPaths::tenant_deploy(tenant_id), &request)
38            .await?;
39        Ok(response.data)
40    }
41
42    pub async fn fetch_secrets(&self, secrets_url: &str) -> Result<TenantSecrets> {
43        let path = secrets_url
44            .strip_prefix(&self.api_url)
45            .unwrap_or(secrets_url);
46        self.get(path).await
47    }
48
49    pub async fn delete_tenant(&self, tenant_id: &str) -> Result<()> {
50        self.delete(&ApiPaths::tenant(tenant_id)).await
51    }
52
53    pub async fn restart_tenant(&self, tenant_id: &str) -> Result<StatusResponse> {
54        self.post_empty(&ApiPaths::tenant_restart(tenant_id)).await
55    }
56
57    pub async fn retry_provision(&self, tenant_id: &str) -> Result<StatusResponse> {
58        self.post_empty(&ApiPaths::tenant_retry_provision(tenant_id))
59            .await
60    }
61
62    pub async fn set_secrets(
63        &self,
64        tenant_id: &str,
65        secrets: std::collections::HashMap<String, String>,
66    ) -> Result<Vec<String>> {
67        let keys: Vec<String> = secrets.keys().cloned().collect();
68        let request = SetSecretsRequest { secrets };
69        self.put_no_content(&ApiPaths::tenant_secrets(tenant_id), &request)
70            .await?;
71        Ok(keys)
72    }
73
74    pub async fn unset_secret(&self, tenant_id: &str, key: &str) -> Result<()> {
75        let path = format!("{}/{}", ApiPaths::tenant_secrets(tenant_id), key);
76        self.delete(&path).await
77    }
78
79    pub async fn set_external_db_access(
80        &self,
81        tenant_id: &str,
82        enabled: bool,
83    ) -> Result<ExternalDbAccessResponse> {
84        let request = SetExternalDbAccessRequest { enabled };
85        let response: ApiResponse<ExternalDbAccessResponse> = self
86            .put(&ApiPaths::tenant_external_db_access(tenant_id), &request)
87            .await?;
88        Ok(response.data)
89    }
90
91    pub async fn rotate_credentials(&self, tenant_id: &str) -> Result<RotateCredentialsResponse> {
92        self.post_empty(&ApiPaths::tenant_rotate_credentials(tenant_id))
93            .await
94    }
95
96    pub async fn rotate_sync_token(&self, tenant_id: &str) -> Result<RotateSyncTokenResponse> {
97        let response: ApiResponse<RotateSyncTokenResponse> = self
98            .post_empty(&ApiPaths::tenant_rotate_sync_token(tenant_id))
99            .await?;
100        Ok(response.data)
101    }
102
103    pub async fn list_secrets(&self, tenant_id: &str) -> Result<ListSecretsResponse> {
104        self.get(&ApiPaths::tenant_secrets(tenant_id)).await
105    }
106
107    pub async fn set_custom_domain(
108        &self,
109        tenant_id: &str,
110        domain: &str,
111    ) -> Result<CustomDomainResponse> {
112        let request = SetCustomDomainRequest {
113            domain: domain.to_string(),
114        };
115        let response: ApiResponse<CustomDomainResponse> = self
116            .post(&ApiPaths::tenant_custom_domain(tenant_id), &request)
117            .await?;
118        Ok(response.data)
119    }
120
121    pub async fn get_custom_domain(&self, tenant_id: &str) -> Result<CustomDomainResponse> {
122        let response: ApiResponse<CustomDomainResponse> =
123            self.get(&ApiPaths::tenant_custom_domain(tenant_id)).await?;
124        Ok(response.data)
125    }
126
127    pub async fn delete_custom_domain(&self, tenant_id: &str) -> Result<()> {
128        self.delete(&ApiPaths::tenant_custom_domain(tenant_id))
129            .await
130    }
131
132    pub async fn cancel_subscription(&self, tenant_id: &str) -> Result<()> {
133        self.post_empty(&ApiPaths::tenant_subscription_cancel(tenant_id))
134            .await
135    }
136}