sos_database/
preferences.rs

1use crate::{
2    entity::{AccountEntity, PreferenceEntity, PreferenceRow},
3    Error,
4};
5use async_sqlite::Client;
6use async_trait::async_trait;
7use sos_core::AccountId;
8use sos_preferences::{Preference, PreferenceMap, PreferencesStorage};
9
10/// Store preferences in a database table.
11pub struct PreferenceProvider<E>
12where
13    E: std::error::Error
14        + std::fmt::Debug
15        + From<Error>
16        + From<sos_preferences::Error>
17        + Send
18        + Sync
19        + 'static,
20{
21    client: Client,
22    marker: std::marker::PhantomData<E>,
23}
24
25impl<E> PreferenceProvider<E>
26where
27    E: std::error::Error
28        + std::fmt::Debug
29        + From<Error>
30        + From<sos_preferences::Error>
31        + Send
32        + Sync
33        + 'static,
34{
35    /// Create a new preferences database provider.
36    pub fn new(client: Client) -> Self {
37        Self {
38            client,
39            marker: std::marker::PhantomData,
40        }
41    }
42}
43
44#[async_trait]
45impl<E> PreferencesStorage for PreferenceProvider<E>
46where
47    E: std::error::Error
48        + std::fmt::Debug
49        + From<Error>
50        + From<sos_preferences::Error>
51        + Send
52        + Sync
53        + 'static,
54{
55    type Error = E;
56
57    async fn load_preferences(
58        &self,
59        account_id: Option<&AccountId>,
60    ) -> Result<PreferenceMap, Self::Error> {
61        let account_id = account_id.cloned();
62        let rows =
63            self.client
64                .conn_and_then(move |conn| match account_id {
65                    Some(account_id) => {
66                        let account = AccountEntity::new(&conn);
67                        let account_row =
68                            account.find_optional(&account_id)?;
69                        let prefs = PreferenceEntity::new(&conn);
70                        Ok::<_, Error>(prefs.load_preferences(
71                            account_row.map(|r| r.row_id),
72                        )?)
73                    }
74                    None => {
75                        let prefs = PreferenceEntity::new(&conn);
76                        Ok::<_, Error>(prefs.load_preferences(None)?)
77                    }
78                })
79                .await?;
80
81        let mut map: PreferenceMap = Default::default();
82        for row in rows {
83            let (key, pref) = row.try_into()?;
84            map.insert(key, pref);
85        }
86        Ok(map)
87    }
88
89    async fn insert_preference(
90        &self,
91        account_id: Option<&AccountId>,
92        key: &str,
93        pref: &Preference,
94    ) -> Result<(), Self::Error> {
95        let account_id = account_id.cloned();
96        let row = PreferenceRow::new_update(key, pref)?;
97        Ok(self
98            .client
99            .conn(move |conn| match account_id {
100                Some(account_id) => {
101                    let account = AccountEntity::new(&conn);
102                    let account_row = account.find_optional(&account_id)?;
103                    let prefs = PreferenceEntity::new(&conn);
104                    Ok(prefs.upsert_preference(
105                        account_row.map(|r| r.row_id),
106                        &row,
107                    )?)
108                }
109                None => {
110                    let prefs = PreferenceEntity::new(&conn);
111                    Ok(prefs.upsert_preference(None, &row)?)
112                }
113            })
114            .await
115            .map_err(Error::from)?)
116    }
117
118    async fn remove_preference(
119        &self,
120        account_id: Option<&AccountId>,
121        key: &str,
122    ) -> Result<(), Self::Error> {
123        let account_id = account_id.cloned();
124        let key = key.to_owned();
125        Ok(self
126            .client
127            .conn(move |conn| match account_id {
128                Some(account_id) => {
129                    let account = AccountEntity::new(&conn);
130                    let account_row = account.find_optional(&account_id)?;
131                    let prefs = PreferenceEntity::new(&conn);
132                    Ok(prefs.delete_preference(
133                        account_row.map(|r| r.row_id),
134                        &key,
135                    )?)
136                }
137                None => {
138                    let prefs = PreferenceEntity::new(&conn);
139                    Ok(prefs.delete_preference(None, &key)?)
140                }
141            })
142            .await
143            .map_err(Error::from)?)
144    }
145
146    async fn clear_preferences(
147        &self,
148        account_id: Option<&AccountId>,
149    ) -> Result<(), Self::Error> {
150        let account_id = account_id.cloned();
151        Ok(self
152            .client
153            .conn(move |conn| match account_id {
154                Some(account_id) => {
155                    let account = AccountEntity::new(&conn);
156                    let account_row = account.find_optional(&account_id)?;
157                    let prefs = PreferenceEntity::new(&conn);
158                    Ok(prefs.delete_all_preferences(
159                        account_row.map(|r| r.row_id),
160                    )?)
161                }
162                None => {
163                    let prefs = PreferenceEntity::new(&conn);
164                    Ok(prefs.delete_all_preferences(None)?)
165                }
166            })
167            .await
168            .map_err(Error::from)?)
169    }
170}