Skip to main content

unifly_api/session/
sites.rs

1// Session API site endpoints
2//
3// Site listing is controller-scoped (not site-scoped), using
4// `/api/self/sites` rather than the usual `/api/s/{site}/...` pattern.
5
6use serde_json::json;
7use tracing::debug;
8
9use crate::error::Error;
10use crate::session::client::SessionClient;
11use crate::session::models::SessionSite;
12
13impl SessionClient {
14    /// List all sites visible to the authenticated user.
15    ///
16    /// `GET /api/self/sites` (controller-level, not site-scoped)
17    pub async fn list_sites(&self) -> Result<Vec<SessionSite>, Error> {
18        let url = self.api_url("self/sites");
19        debug!("listing sites");
20        self.get(url).await
21    }
22
23    /// Get all site settings.
24    ///
25    /// `GET /api/s/{site}/rest/setting`
26    pub async fn get_site_settings(&self) -> Result<Vec<serde_json::Value>, Error> {
27        let url = self.site_url("rest/setting");
28        debug!("fetching site settings");
29        self.get(url).await
30    }
31
32    /// Create a new site.
33    ///
34    /// `POST /api/s/{site}/cmd/sitemgr` with `{"cmd": "add-site", "name": "...", "desc": "..."}`
35    pub async fn create_site(&self, name: &str, description: &str) -> Result<(), Error> {
36        let url = self.site_url("cmd/sitemgr");
37        debug!(name, "creating site");
38        let _: Vec<serde_json::Value> = self
39            .post(
40                url,
41                &json!({
42                    "cmd": "add-site",
43                    "name": name,
44                    "desc": description,
45                }),
46            )
47            .await?;
48        Ok(())
49    }
50
51    /// Delete a site.
52    ///
53    /// `POST /api/s/{site}/cmd/sitemgr` with `{"cmd": "delete-site", "name": "..."}`
54    pub async fn delete_site(&self, name: &str) -> Result<(), Error> {
55        let url = self.site_url("cmd/sitemgr");
56        debug!(name, "deleting site");
57        let _: Vec<serde_json::Value> = self
58            .post(
59                url,
60                &json!({
61                    "cmd": "delete-site",
62                    "name": name,
63                }),
64            )
65            .await?;
66        Ok(())
67    }
68
69    /// Invite a site administrator.
70    ///
71    /// `POST /api/s/{site}/cmd/sitemgr` with `{"cmd": "invite-admin", ...}`
72    pub async fn invite_admin(&self, name: &str, email: &str, role: &str) -> Result<(), Error> {
73        let url = self.site_url("cmd/sitemgr");
74        debug!(name, email, role, "inviting admin");
75        let _: Vec<serde_json::Value> = self
76            .post(
77                url,
78                &json!({
79                    "cmd": "invite-admin",
80                    "name": name,
81                    "email": email,
82                    "role": role,
83                }),
84            )
85            .await?;
86        Ok(())
87    }
88
89    /// Revoke a site administrator.
90    ///
91    /// `POST /api/s/{site}/cmd/sitemgr` with `{"cmd": "revoke-admin", "admin": "..."}`
92    pub async fn revoke_admin(&self, admin_id: &str) -> Result<(), Error> {
93        let url = self.site_url("cmd/sitemgr");
94        debug!(admin_id, "revoking admin");
95        let _: Vec<serde_json::Value> = self
96            .post(
97                url,
98                &json!({
99                    "cmd": "revoke-admin",
100                    "admin": admin_id,
101                }),
102            )
103            .await?;
104        Ok(())
105    }
106
107    /// Update a site setting.
108    ///
109    /// `PUT /api/s/{site}/set/setting/{key}` with an arbitrary JSON body.
110    pub async fn set_site_setting(&self, key: &str, body: &serde_json::Value) -> Result<(), Error> {
111        let url = self.site_url(&format!("set/setting/{key}"));
112        debug!(key, "updating site setting");
113        let _: Vec<serde_json::Value> = self.put(url, body).await?;
114        Ok(())
115    }
116
117    /// Update site administrator role.
118    ///
119    /// `POST /api/s/{site}/cmd/sitemgr` with `{"cmd": "update-admin", ...}`
120    pub async fn update_admin(&self, admin_id: &str, role: Option<&str>) -> Result<(), Error> {
121        let url = self.site_url("cmd/sitemgr");
122        debug!(admin_id, ?role, "updating admin");
123        let mut body = serde_json::Map::new();
124        body.insert(
125            "cmd".into(),
126            serde_json::Value::String("update-admin".into()),
127        );
128        body.insert(
129            "admin".into(),
130            serde_json::Value::String(admin_id.to_owned()),
131        );
132        if let Some(role) = role {
133            body.insert("role".into(), serde_json::Value::String(role.to_owned()));
134        }
135        let _: Vec<serde_json::Value> = self.post(url, &serde_json::Value::Object(body)).await?;
136        Ok(())
137    }
138}