1use base64::{engine::general_purpose, Engine};
2use reqwest::{
3 header::{HeaderMap, HeaderValue, AUTHORIZATION},
4 Client,
5};
6
7use log::{error, trace};
8
9use crate::models::{Page, PostPage, Space, SpaceContentResult, SpacesResult};
10
11pub mod models;
12
13pub struct Session {
14 base_url: String,
15 client: Client,
16}
17
18impl Session {
19 pub fn new(username: String, api_key: String, base_url: String) -> Session {
20 let auth_header_val = general_purpose::STANDARD.encode(format!("{}:{}", username, api_key));
21
22 let mut headers = HeaderMap::new();
23 headers.insert(
24 AUTHORIZATION,
25 HeaderValue::from_str(&format!("Basic {auth_header_val}")).unwrap(),
26 );
27
28 let client = reqwest::Client::builder()
29 .default_headers(headers)
30 .build()
31 .unwrap();
32
33 Session { base_url, client }
34 }
35
36 pub async fn get_page_by_id(&self, id: u64) -> Result<Page, ()> {
37 let url = format!("{}/rest/api/content/{}", self.base_url, id);
38 trace!("GET {}", url);
39 let response = self
40 .client
41 .get(url)
42 .query(&[("expand", "body.view,space,children.page,version")])
43 .send()
44 .await
45 .unwrap();
46 if response.status().is_client_error() || response.status().is_server_error() {
47 error!("Error getting page: {}", response.text().await.unwrap());
48 return Err(());
49 }
50 let page: Page = serde_json::from_str(&response.text().await.unwrap()).unwrap();
51 Ok(page)
52 }
53
54 pub async fn get_spaces(&self) -> Result<Vec<Space>, ()> {
55 let url = format!("{}/rest/api/space", self.base_url);
56 trace!("GET {}", url);
57 let response = self
58 .client
59 .get(url)
60 .query(&[("type", "global")])
61 .send()
62 .await
63 .unwrap();
64 if response.status().is_client_error() || response.status().is_server_error() {
65 error!("Error getting page: {}", response.text().await.unwrap());
66 return Err(());
67 }
68 let result: SpacesResult = serde_json::from_str(&response.text().await.unwrap()).unwrap();
69 Ok(result.results)
70 }
71
72 #[async_recursion::async_recursion]
73 pub async fn get_pages_for_space(
74 &self,
75 space_key: &str,
76 next: Option<String>,
77 ) -> Result<Vec<Page>, ()> {
78 let url = if next.is_some() {
79 format!("{}{}", self.base_url, next.unwrap().replace("/page", ""))
80 } else {
81 format!("{}/rest/api/space/{}/content", self.base_url, space_key)
82 };
83 trace!("GET {}", url);
84 let response = self
85 .client
86 .get(url)
87 .query(&[("expand", "body.view,space,children.page,version")])
88 .send()
89 .await
90 .unwrap();
91 if response.status().is_client_error() || response.status().is_server_error() {
92 error!("Error getting page: {}", response.text().await.unwrap());
93 return Err(());
94 }
95 let result: SpaceContentResult =
96 serde_json::from_str(&response.text().await.unwrap()).unwrap();
97 let mut pages = result.page.results;
98 if result.page.links.next.is_some() {
99 let mut next_pages = self
100 .get_pages_for_space(space_key, result.page.links.next)
101 .await
102 .unwrap();
103 pages.append(&mut next_pages);
104 return Ok(pages);
105 }
106 Ok(pages)
107 }
108
109 pub async fn add_new_page(
110 &self,
111 space_key: String,
112 ancestor: Option<u64>,
113 title: String,
114 body: Option<String>,
115 ) -> Result<Page, ()> {
116 let url = format!("{}/rest/api/content", self.base_url);
117 trace!("POST {}", url);
118 let response = self
119 .client
120 .post(url)
121 .query(&[("expand", "body.view,space,children.page,version")])
122 .json(&PostPage::new_new_page(title, ancestor, space_key, body))
123 .send()
124 .await
125 .unwrap();
126 if response.status().is_client_error() || response.status().is_server_error() {
127 error!("Error adding new page: {}", response.text().await.unwrap());
128 return Err(());
129 }
130 let page: Page = serde_json::from_str(&response.text().await.unwrap()).unwrap();
131 Ok(page)
132 }
133
134 pub async fn update_page(
135 &self,
136 space_key: String,
137 id: u64,
138 new_version: u64,
139 title: String,
140 body: Option<String>,
141 ) -> Result<Page, ()> {
142 let url = format!("{}/rest/api/content/{}", self.base_url, id);
143 trace!("PUT {}", url);
144 let response = self
145 .client
146 .put(url)
147 .query(&[("expand", "body.view,space,children.page,version")])
148 .json(&PostPage::new_update_page(
149 id,
150 title,
151 space_key,
152 body,
153 new_version,
154 ))
155 .send()
156 .await
157 .unwrap();
158 if response.status().is_client_error() || response.status().is_server_error() {
159 error!("Error updating page: {}", response.text().await.unwrap());
160 return Err(());
161 }
162 let page: Page = serde_json::from_str(&response.text().await.unwrap()).unwrap();
163 Ok(page)
164 }
165}
166
167#[cfg(test)]
168mod tests {
169 use super::*;
170
171 #[test]
172 fn test_session_creation() {
173 let _session = Session::new("".to_owned(), "".to_owned(), "".to_owned());
174 }
175}