Skip to main content

gout_api/
admin.rs

1//! `GoutAdminClient` — 使用 admin key 管理 goutd。
2//!
3//! 负责 API key 的创建、列出和删除。
4//! 需要服务端启动时打印的 `admin-api-key`。
5
6use crate::{ApiResponse, CreateKeyRequest, CreateKeyResponse, KeyInfo};
7use anyhow::{Context, Result};
8
9/// 管理客户端。
10///
11/// 使用 `admin-api-key`(非普通隧道 key)进行认证。
12/// 用于创建/删除普通隧道 key。
13///
14/// # 示例
15///
16/// ```no_run
17/// # async fn doc() {
18/// use gout_api::admin::GoutAdminClient;
19///
20/// let admin = GoutAdminClient::new("server.example.com:8080", "admin-key");
21/// let key = admin.create_key("my laptop").await.unwrap();
22/// println!("new key: {}", key.key);
23/// # }
24/// ```
25pub struct GoutAdminClient {
26    inner: reqwest::Client,
27    base: String,
28    admin_key: String,
29}
30
31impl GoutAdminClient {
32    /// 创建一个新的 `GoutAdminClient`。
33    ///
34    /// # 参数
35    ///
36    /// * `server_addr` — 服务端地址,`host:port` 格式
37    /// * `admin_key` — 服务端首次启动时打印到 stdout 的 admin API key
38    pub fn new(server_addr: &str, admin_key: &str) -> Self {
39        Self {
40            inner: reqwest::Client::new(),
41            base: format!("http://{server_addr}"),
42            admin_key: admin_key.to_string(),
43        }
44    }
45
46    /// 创建一个普通 API key。
47    ///
48    /// 该 key 可用于 [`GoutClient`](crate::client::GoutClient) 进行隧道操作。
49    ///
50    /// # 参数
51    ///
52    /// * `name` — key 的备注名称(如 `"my laptop"`)
53    pub async fn create_key(&self, name: &str) -> Result<CreateKeyResponse> {
54        let resp = self
55            .inner
56            .post(format!("{}/api/v1/keys", self.base))
57            .header("X-Admin-Key", &self.admin_key)
58            .json(&CreateKeyRequest { name: name.into() })
59            .send()
60            .await
61            .context("REST create key failed")?;
62
63        if !resp.status().is_success() {
64            let j: ApiResponse<CreateKeyResponse> = resp.json().await?;
65            anyhow::bail!("{}", j.error.unwrap_or_default());
66        }
67
68        let j: ApiResponse<CreateKeyResponse> = resp.json().await?;
69        j.data.context("no key data")
70    }
71
72    /// 列出所有普通 API key。
73    ///
74    /// 返回的列表中不包含 admin key。
75    pub async fn list_keys(&self) -> Result<Vec<KeyInfo>> {
76        let resp = self
77            .inner
78            .get(format!("{}/api/v1/keys", self.base))
79            .header("X-Admin-Key", &self.admin_key)
80            .send()
81            .await
82            .context("REST list keys failed")?;
83
84        let j: ApiResponse<Vec<KeyInfo>> = resp.json().await?;
85        Ok(j.data.unwrap_or_default())
86    }
87
88    /// 删除一个 API key。
89    ///
90    /// 返回 `true` 表示删除成功,`false` 表示 key 不存在。
91    /// 不允许删除 admin key。
92    pub async fn delete_key(&self, key: &str) -> Result<bool> {
93        let resp = self
94            .inner
95            .delete(format!("{}/api/v1/keys/{}", self.base, key))
96            .header("X-Admin-Key", &self.admin_key)
97            .send()
98            .await
99            .context("REST delete key failed")?;
100
101        let j: ApiResponse<()> = resp.json().await?;
102        Ok(j.success)
103    }
104
105    /// 获取 admin key 值。
106    pub fn admin_key(&self) -> &str {
107        &self.admin_key
108    }
109}