Skip to main content

dsc/api/
settings.rs

1use super::client::DiscourseClient;
2use super::error::http_error;
3use anyhow::{anyhow, Context, Result};
4use serde_json::Value;
5
6impl DiscourseClient {
7    /// Update a site setting by name (admin only).
8    pub fn update_site_setting(&self, setting: &str, value: &str) -> Result<()> {
9        let setting = setting.trim();
10        if setting.is_empty() {
11            return Err(anyhow!("missing site setting name for site setting update"));
12        }
13        if setting.chars().any(|ch| ch.is_whitespace() || ch == '/') {
14            return Err(anyhow!(
15                "site setting name contains invalid characters: {}",
16                setting
17            ));
18        }
19        let payload = [("value", value)];
20        let response = self
21            .put(&format!("/admin/site_settings/{}.json", setting))?
22            .form(&payload)
23            .send()
24            .context("updating site setting")?;
25        let status = response.status();
26        let text = response
27            .text()
28            .context("reading site setting update response")?;
29        if !status.is_success() {
30            return Err(http_error("update site setting request", status, &text));
31        }
32        Ok(())
33    }
34
35    /// Fetch all site settings (admin only). Returns raw JSON value.
36    pub fn list_site_settings(&self) -> Result<Value> {
37        let response = self.get("/admin/site_settings.json")?;
38        let status = response.status();
39        let text = response
40            .text()
41            .context("reading site settings list response")?;
42        if !status.is_success() {
43            return Err(http_error("list site settings request", status, &text));
44        }
45        let value: Value =
46            serde_json::from_str(&text).context("parsing site settings list response")?;
47        Ok(value)
48    }
49
50    /// Fetch a single site setting by name (admin only).
51    /// Returns the value as a string, or an error if not found.
52    pub fn fetch_site_setting(&self, setting: &str) -> Result<String> {
53        let setting = setting.trim();
54        if setting.is_empty() {
55            return Err(anyhow!("missing site setting name"));
56        }
57        // The admin site settings API returns all settings; we filter by name.
58        let all = self.list_site_settings()?;
59        // Response shape: { "site_settings": [ { "setting": "...", "value": ... }, ... ] }
60        let settings = all
61            .get("site_settings")
62            .and_then(|v| v.as_array())
63            .cloned()
64            .unwrap_or_default();
65        for entry in &settings {
66            let name = entry.get("setting").and_then(|v| v.as_str()).unwrap_or("");
67            if name == setting {
68                let value = entry.get("value").cloned().unwrap_or(Value::Null);
69                let display = match &value {
70                    Value::String(s) => s.clone(),
71                    Value::Null => String::new(),
72                    other => other.to_string(),
73                };
74                return Ok(display);
75            }
76        }
77        Err(anyhow!("setting not found: {}", setting))
78    }
79}