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 = self
63            .client
64            .conn_and_then(move |conn| match account_id {
65                Some(account_id) => {
66                    let account = AccountEntity::new(&conn);
67                    let account_row = account.find_one(&account_id)?;
68                    let prefs = PreferenceEntity::new(&conn);
69                    Ok::<_, Error>(
70                        prefs.load_preferences(Some(account_row.row_id))?,
71                    )
72                }
73                None => {
74                    let prefs = PreferenceEntity::new(&conn);
75                    Ok::<_, Error>(prefs.load_preferences(None)?)
76                }
77            })
78            .await?;
79
80        let mut map: PreferenceMap = Default::default();
81        for row in rows {
82            let (key, pref) = row.try_into()?;
83            map.inner_mut().insert(key, pref);
84        }
85        Ok(map)
86    }
87
88    async fn insert_preference(
89        &self,
90        account_id: Option<&AccountId>,
91        key: &str,
92        pref: &Preference,
93    ) -> Result<(), Self::Error> {
94        let account_id = account_id.cloned();
95        let row = PreferenceRow::new_update(key, pref)?;
96        Ok(self
97            .client
98            .conn(move |conn| match account_id {
99                Some(account_id) => {
100                    let account = AccountEntity::new(&conn);
101                    let account_row = account.find_one(&account_id)?;
102                    let prefs = PreferenceEntity::new(&conn);
103                    Ok(prefs
104                        .upsert_preference(Some(account_row.row_id), &row)?)
105                }
106                None => {
107                    let prefs = PreferenceEntity::new(&conn);
108                    Ok(prefs.upsert_preference(None, &row)?)
109                }
110            })
111            .await
112            .map_err(Error::from)?)
113    }
114
115    async fn remove_preference(
116        &self,
117        account_id: Option<&AccountId>,
118        key: &str,
119    ) -> Result<(), Self::Error> {
120        let account_id = account_id.cloned();
121        let key = key.to_owned();
122        Ok(self
123            .client
124            .conn(move |conn| match account_id {
125                Some(account_id) => {
126                    let account = AccountEntity::new(&conn);
127                    let account_row = account.find_one(&account_id)?;
128                    let prefs = PreferenceEntity::new(&conn);
129                    Ok(prefs
130                        .delete_preference(Some(account_row.row_id), &key)?)
131                }
132                None => {
133                    let prefs = PreferenceEntity::new(&conn);
134                    Ok(prefs.delete_preference(None, &key)?)
135                }
136            })
137            .await
138            .map_err(Error::from)?)
139    }
140
141    async fn clear_preferences(
142        &self,
143        account_id: Option<&AccountId>,
144    ) -> Result<(), Self::Error> {
145        let account_id = account_id.cloned();
146        Ok(self
147            .client
148            .conn(move |conn| match account_id {
149                Some(account_id) => {
150                    let account = AccountEntity::new(&conn);
151                    let account_row = account.find_one(&account_id)?;
152                    let prefs = PreferenceEntity::new(&conn);
153                    Ok(prefs
154                        .delete_all_preferences(Some(account_row.row_id))?)
155                }
156                None => {
157                    let prefs = PreferenceEntity::new(&conn);
158                    Ok(prefs.delete_all_preferences(None)?)
159                }
160            })
161            .await
162            .map_err(Error::from)?)
163    }
164}