couchdb_orm/client/couchdb/actions/db/create/
mod.rs

1// Copyright (C) 2020-2023  OpenToolAdd
2//
3// This program is free software: you can redistribute it and/or modify
4// it under the terms of the GNU General Public License as published by
5// the Free Software Foundation, either version 3 of the License, or
6// (at your option) any later version.
7//
8// This program is distributed in the hope that it will be useful,
9// but WITHOUT ANY WARRANTY; without even the implied warranty of
10// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11// GNU General Public License for more details.
12//
13// You should have received a copy of the GNU General Public License
14// along with this program.  If not, see <http://www.gnu.org/licenses/>.
15// contact: contact@tool-add.com
16
17use crate::regexes::COUCHDB_DB_RULE;
18use awc::Client;
19
20pub mod errors;
21
22use errors::DBCreationError;
23
24pub async fn create_db(
25    client: &Client,
26    db_name: &str,
27    host: &str,
28) -> Result<bool, Box<dyn std::error::Error>> {
29    if !COUCHDB_DB_RULE.is_match(db_name) {
30        return Err(Box::new(DBCreationError::new(&format!(
31            "{} string doesn't respect the regex rule {}",
32            db_name,
33            COUCHDB_DB_RULE.as_str()
34        ))));
35    }
36    let uri: String = format!("{}/{}", host, db_name,);
37    match client.put(&uri).send().await {
38        Ok(mut response) => {
39            // println!("{:?}", response);
40            if response.status().as_u16() >= 400 {
41                let bytes: Vec<u8> = response.body().await?.iter().cloned().collect();
42                let error: serde_json::Value =
43                    serde_json::from_str(std::str::from_utf8(bytes.as_slice()).unwrap()).unwrap();
44                Err(Box::new(DBCreationError::new(&format!(
45                    "Error with the request to {}: error: \n{}",
46                    &uri, error
47                ))))
48            } else {
49                Ok(true)
50            }
51        }
52        Err(error) => Err(Box::new(DBCreationError::new(&format!(
53            "Error with the request to {}: error: \n{}",
54            host, error
55        )))),
56    }
57}
58
59#[cfg(test)]
60mod tests {
61    extern crate actix_web;
62    extern crate wiremock;
63
64    use super::*;
65    use actix_web::test;
66    use dotenv::dotenv;
67    use serde_json::Value;
68    use std::error::Error;
69
70    use wiremock::matchers::{method, path};
71    use wiremock::{Mock, MockServer, ResponseTemplate};
72
73    #[actix_rt::test]
74    async fn create_db_regex_error_test() {
75        let client: Client = Client::default();
76        let box_result: Box<dyn Error> = create_db(&client, "Test", "").await.unwrap_err();
77        let result: &DBCreationError = box_result.downcast_ref().unwrap();
78        assert_eq!(
79            format!("{}", result),
80            format!(
81                "DBCreationError: {} string doesn't respect the regex rule {}",
82                "Test",
83                COUCHDB_DB_RULE.as_str()
84            )
85        );
86
87        let box_result: Box<dyn Error> = create_db(&client, "testT", "").await.unwrap_err();
88        let result: &DBCreationError = box_result.downcast_ref().unwrap();
89        assert_eq!(
90            format!("{}", result),
91            format!(
92                "DBCreationError: {} string doesn't respect the regex rule {}",
93                "testT",
94                COUCHDB_DB_RULE.as_str()
95            )
96        )
97    }
98
99    #[actix_rt::test]
100    async fn create_db_http_error_test() {
101        let mock_server = MockServer::start().await;
102        // Some JSON input data as a &str. Maybe this comes from the user.
103        let data = r#"
104        {
105            "error": "test error"
106        }"#;
107
108        let response_template: ResponseTemplate =
109            ResponseTemplate::new(400).set_body_raw(data.as_bytes(), "application/json");
110        Mock::given(method("PUT"))
111            .and(path("/test"))
112            .respond_with(response_template)
113            .mount(&mock_server)
114            .await;
115
116        let error: serde_json::Value = serde_json::from_str(data).unwrap();
117
118        let client: Client = Client::default();
119        let host: String = mock_server.uri();
120
121        let box_result: Box<dyn Error> = create_db(&client, "test", &host).await.unwrap_err();
122        let result: &DBCreationError = box_result.downcast_ref().unwrap();
123        assert_eq!(
124            format!("{}", result),
125            format!(
126                "DBCreationError: Error with the request to {}: error: \n{}",
127                format!("{}/{}", host, "test"),
128                error
129            )
130        )
131    }
132
133    #[actix_rt::test]
134    async fn create_db_test() {
135        let mock_server = MockServer::start().await;
136        Mock::given(method("PUT"))
137            .and(path("/test"))
138            .respond_with(ResponseTemplate::new(200))
139            .mount(&mock_server)
140            .await;
141
142        let client: Client = Client::default();
143        let host: String = mock_server.uri();
144        println!("test host: {}", host);
145        assert_eq!(create_db(&client, "test", &host).await.unwrap(), true);
146    }
147}