sos_database/
server_origins.rs

1use crate::{
2    entity::{AccountEntity, ServerEntity, ServerRow},
3    Error,
4};
5use async_sqlite::Client;
6use async_trait::async_trait;
7use sos_core::{AccountId, Origin, RemoteOrigins};
8use std::collections::HashSet;
9
10/// Collection of server origins.
11pub struct ServerOrigins<E>
12where
13    E: std::error::Error
14        + std::fmt::Debug
15        + From<Error>
16        + Send
17        + Sync
18        + 'static,
19{
20    client: Client,
21    account_id: AccountId,
22    marker: std::marker::PhantomData<E>,
23}
24
25impl<E> ServerOrigins<E>
26where
27    E: std::error::Error
28        + std::fmt::Debug
29        + From<Error>
30        + Send
31        + Sync
32        + 'static,
33{
34    /// Create new server origins.
35    pub fn new(account_id: AccountId, client: Client) -> Self {
36        Self {
37            client,
38            account_id,
39            marker: std::marker::PhantomData,
40        }
41    }
42
43    async fn list_origins(&self) -> Result<HashSet<Origin>, E> {
44        let account_id = self.account_id;
45        let servers = self
46            .client
47            .conn_and_then(move |conn| {
48                let accounts = AccountEntity::new(&conn);
49                let account_row = accounts.find_one(&account_id)?;
50                let servers = ServerEntity::new(&conn);
51                servers.load_servers(account_row.row_id)
52            })
53            .await?;
54        let mut set = HashSet::new();
55        for server in servers {
56            set.insert(server.try_into()?);
57        }
58        Ok(set)
59    }
60
61    async fn insert_server(
62        &mut self,
63        origin: Origin,
64        remove: Option<&Origin>,
65    ) -> Result<(), E> {
66        let account_id = self.account_id;
67        let remove = remove.cloned();
68        let server_row: ServerRow = origin.try_into()?;
69        self.client
70            .conn_mut(move |conn| {
71                let tx = conn.transaction()?;
72                let accounts = AccountEntity::new(&tx);
73                let account_row = accounts.find_one(&account_id)?;
74                let servers = ServerEntity::new(&tx);
75
76                if let Some(remove) = remove {
77                    let server_row =
78                        servers.find_one(account_row.row_id, remove.url())?;
79                    servers.delete_server(server_row.row_id)?;
80                }
81
82                servers.insert_server(account_row.row_id, &server_row)?;
83
84                tx.commit()?;
85                Ok(())
86            })
87            .await
88            .map_err(Error::from)?;
89        Ok(())
90    }
91}
92
93#[async_trait]
94impl<E> RemoteOrigins for ServerOrigins<E>
95where
96    E: std::error::Error
97        + std::fmt::Debug
98        + From<Error>
99        + Send
100        + Sync
101        + 'static,
102{
103    type Error = E;
104
105    async fn list_servers(&self) -> Result<HashSet<Origin>, Self::Error> {
106        self.list_origins().await
107    }
108
109    async fn add_server(
110        &mut self,
111        origin: Origin,
112    ) -> Result<(), Self::Error> {
113        let account_id = self.account_id;
114        let url = origin.url().clone();
115        let server_row = self
116            .client
117            .conn(move |conn| {
118                let accounts = AccountEntity::new(&conn);
119                let account_row = accounts.find_one(&account_id)?;
120                let servers = ServerEntity::new(&conn);
121                servers.find_optional(account_row.row_id, &url)
122            })
123            .await
124            .map_err(Error::from)?;
125
126        match server_row {
127            Some(row) => {
128                let old_origin: Origin = row.try_into()?;
129                self.insert_server(origin, Some(&old_origin)).await
130            }
131            None => self.insert_server(origin, None).await,
132        }
133    }
134
135    async fn replace_server(
136        &mut self,
137        old_origin: &Origin,
138        new_origin: Origin,
139    ) -> Result<(), Self::Error> {
140        self.insert_server(new_origin, Some(old_origin)).await
141    }
142
143    async fn remove_server(
144        &mut self,
145        origin: &Origin,
146    ) -> Result<(), Self::Error> {
147        let account_id = self.account_id;
148        let origin = origin.clone();
149        self.client
150            .conn_mut(move |conn| {
151                let tx = conn.transaction()?;
152                let accounts = AccountEntity::new(&tx);
153                let account_row = accounts.find_one(&account_id)?;
154                let servers = ServerEntity::new(&tx);
155                let server_row =
156                    servers.find_one(account_row.row_id, origin.url())?;
157                servers.delete_server(server_row.row_id)?;
158                tx.commit()?;
159                Ok(())
160            })
161            .await
162            .map_err(Error::from)?;
163
164        Ok(())
165    }
166}