src/backend.rs 4.3 K raw
1
use crate::db::{self, Db, Snippet};
2
use std::fmt;
3
4
pub enum BackendError {
5
    NotFound,
6
    Unauthorized(String),
7
    Network(String),
8
}
9
10
impl fmt::Display for BackendError {
11
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
12
        match self {
13
            BackendError::NotFound => write!(f, "Not found"),
14
            BackendError::Unauthorized(msg) => write!(f, "Unauthorized: {}", msg),
15
            BackendError::Network(msg) => write!(f, "Network error: {}", msg),
16
        }
17
    }
18
}
19
20
pub enum Backend {
21
    Local {
22
        db: Db,
23
    },
24
    Remote {
25
        base_url: String,
26
        api_key: Option<String>,
27
        client: reqwest::blocking::Client,
28
    },
29
}
30
31
impl Backend {
32
    pub fn local() -> Self {
33
        Backend::Local { db: db::init_db() }
34
    }
35
36
    pub fn remote(base_url: String, api_key: Option<String>) -> Self {
37
        Backend::Remote {
38
            base_url,
39
            api_key,
40
            client: reqwest::blocking::Client::new(),
41
        }
42
    }
43
44
    pub fn list_snippets(&self) -> Result<Vec<Snippet>, BackendError> {
45
        match self {
46
            Backend::Local { db } => Ok(db::get_all_snippets(db)),
47
            Backend::Remote {
48
                base_url,
49
                api_key,
50
                client,
51
            } => {
52
                let mut req = client.get(format!("{}/api/snippets", base_url));
53
                if let Some(key) = api_key {
54
                    req = req.header("x-api-key", key);
55
                }
56
                let resp = req.send().map_err(|e| BackendError::Network(e.to_string()))?;
57
                match resp.status().as_u16() {
58
                    200 => resp
59
                        .json::<Vec<Snippet>>()
60
                        .map_err(|e| BackendError::Network(e.to_string())),
61
                    401 => Err(BackendError::Unauthorized("Invalid API key".into())),
62
                    403 => Err(BackendError::Unauthorized("No API key configured on server".into())),
63
                    _ => Err(BackendError::Network(format!("HTTP {}", resp.status()))),
64
                }
65
            }
66
        }
67
    }
68
69
    pub fn create_snippet(&self, name: &str, content: &str) -> Result<Snippet, BackendError> {
70
        match self {
71
            Backend::Local { db } => Ok(db::create_snippet(db, name, content)),
72
            Backend::Remote {
73
                base_url,
74
                api_key,
75
                client,
76
            } => {
77
                let mut req = client
78
                    .post(format!("{}/api/snippets", base_url))
79
                    .json(&serde_json::json!({"name": name, "content": content}));
80
                if let Some(key) = api_key {
81
                    req = req.header("x-api-key", key);
82
                }
83
                let resp = req.send().map_err(|e| BackendError::Network(e.to_string()))?;
84
                match resp.status().as_u16() {
85
                    201 => resp
86
                        .json::<Snippet>()
87
                        .map_err(|e| BackendError::Network(e.to_string())),
88
                    401 => Err(BackendError::Unauthorized("Invalid API key".into())),
89
                    403 => Err(BackendError::Unauthorized("No API key configured on server".into())),
90
                    _ => Err(BackendError::Network(format!("HTTP {}", resp.status()))),
91
                }
92
            }
93
        }
94
    }
95
96
    pub fn delete_snippet(&self, short_id: &str) -> Result<bool, BackendError> {
97
        match self {
98
            Backend::Local { db } => Ok(db::delete_snippet_by_short_id(db, short_id)),
99
            Backend::Remote {
100
                base_url,
101
                api_key,
102
                client,
103
            } => {
104
                let mut req =
105
                    client.delete(format!("{}/api/snippets/{}", base_url, short_id));
106
                if let Some(key) = api_key {
107
                    req = req.header("x-api-key", key);
108
                }
109
                let resp = req.send().map_err(|e| BackendError::Network(e.to_string()))?;
110
                match resp.status().as_u16() {
111
                    200 => Ok(true),
112
                    401 => Err(BackendError::Unauthorized("Invalid API key".into())),
113
                    403 => Err(BackendError::Unauthorized("No API key configured on server".into())),
114
                    404 => Ok(false),
115
                    _ => Err(BackendError::Network(format!("HTTP {}", resp.status()))),
116
                }
117
            }
118
        }
119
    }
120
}