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        self.post_empty(&ApiPaths::tenant_rotate_sync_token(tenant_id))
98            .await
99    }
100
101    pub async fn list_secrets(&self, tenant_id: &str) -> Result<ListSecretsResponse> {
102        self.get(&ApiPaths::tenant_secrets(tenant_id)).await
103    }
104
105    pub async fn set_custom_domain(
106        &self,
107        tenant_id: &str,
108        domain: &str,
109    ) -> Result<CustomDomainResponse> {
110        let request = SetCustomDomainRequest {
111            domain: domain.to_string(),
112        };
113        let response: ApiResponse<CustomDomainResponse> = self
114            .post(&ApiPaths::tenant_custom_domain(tenant_id), &request)
115            .await?;
116        Ok(response.data)
117    }
118
119    pub async fn get_custom_domain(&self, tenant_id: &str) -> Result<CustomDomainResponse> {
120        let response: ApiResponse<CustomDomainResponse> =
121            self.get(&ApiPaths::tenant_custom_domain(tenant_id)).await?;
122        Ok(response.data)
123    }
124
125    pub async fn delete_custom_domain(&self, tenant_id: &str) -> Result<()> {
126        self.delete(&ApiPaths::tenant_custom_domain(tenant_id))
127            .await
128    }
129
130    pub async fn cancel_subscription(&self, tenant_id: &str) -> Result<()> {
131        self.post_empty(&ApiPaths::tenant_subscription_cancel(tenant_id))
132            .await
133    }
134}