sos_database/
server_origins.rs1use 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
10pub 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 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.clone();
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 Ok(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.clone();
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.clone();
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 Ok(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.clone();
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}