1use crate::API_BASE_URL;
2use reqwest::Client;
3use serde::{Deserialize, Serialize};
4use std::error::Error;
5use tracing::debug;
6
7#[derive(Debug, Deserialize, Serialize)]
8pub struct Secret {
9 pub label: String,
10 pub publickey: Vec<i32>,
11 #[serde(rename = "type")]
12 pub stype: String,
13}
14
15#[derive(Debug, Serialize)]
16pub struct SecretValue {
17 pub value: Vec<i32>,
18}
19
20impl SecretValue {
21 pub fn new(value: Vec<i32>) -> Self {
22 Self { value }
23 }
24}
25
26pub struct SecretsManager {
27 client: Client,
28 api_token: String,
29}
30
31impl SecretsManager {
32 pub fn new(client: Client, api_token: String) -> Self {
33 Self { client, api_token }
34 }
35
36 pub async fn list_secrets(&self, app_name: &str) -> Result<Vec<Secret>, Box<dyn Error>> {
37 let url = format!("{API_BASE_URL}/apps/{}/secrets", app_name);
38 let response = self
39 .client
40 .get(&url)
41 .bearer_auth(&self.api_token)
42 .send()
43 .await?;
44
45 if response.status().is_success() {
46 let secrets = response.json::<Vec<Secret>>().await?;
47 debug!("Successfully fetched secrets: {:?}", secrets);
48 Ok(secrets)
49 } else {
50 Err(format!("Failed to fetch secrets: {}", response.status()).into())
51 }
52 }
53
54 pub async fn create_secret(
55 &self,
56 app_name: &str,
57 secret_label: &str,
58 secret_type: &str,
59 value_request: SecretValue,
60 ) -> Result<Secret, Box<dyn Error>> {
61 debug!("Creating secret: {}", secret_label);
62 let url = format!(
63 "{API_BASE_URL}/apps/{}/secrets/{}/type/{}",
64 app_name, secret_label, secret_type
65 );
66 let response = self
67 .client
68 .post(&url)
69 .bearer_auth(&self.api_token)
70 .json(&value_request)
71 .send()
72 .await?;
73
74 let status = response.status();
75 if status.is_success() {
76 let secret = response.json::<Secret>().await?;
77 Ok(secret)
78 } else {
79 let error_text = response.text().await?;
80 Err(format!("Failed to create secret: {} - {}", status, error_text).into())
81 }
82 }
83
84 pub async fn generate_secret(
85 &self,
86 app_name: &str,
87 secret_label: &str,
88 secret_type: &str,
89 ) -> Result<(), Box<dyn Error>> {
90 debug!("Generating secret: {}", secret_label);
91 let url = format!(
92 "{API_BASE_URL}/apps/{}/secrets/{}/type/{}/generate",
93 app_name, secret_label, secret_type
94 );
95 let response = self
96 .client
97 .post(&url)
98 .bearer_auth(&self.api_token)
99 .send()
100 .await?;
101
102 if response.status().is_success() {
103 debug!("Successfully generated secret: {}", secret_label);
104 Ok(())
105 } else {
106 Err(format!("Failed to generate secret: {}", response.status()).into())
107 }
108 }
109
110 pub async fn destroy_secret(
111 &self,
112 app_name: &str,
113 secret_label: &str,
114 ) -> Result<(), Box<dyn Error>> {
115 debug!("Deleting secret: {}", secret_label);
116 let url = format!("{API_BASE_URL}/apps/{}/secrets/{}", app_name, secret_label);
117 let response = self
118 .client
119 .delete(&url)
120 .bearer_auth(&self.api_token)
121 .send()
122 .await?;
123
124 if response.status().is_success() {
125 debug!("Successfully deleted secret: {}", secret_label);
126 Ok(())
127 } else {
128 Err(format!("Failed to delete secret: {}", response.status()).into())
129 }
130 }
131}