sos_database/entity/
system_message.rs

1use crate::Result;
2use async_sqlite::rusqlite::{Connection, Error as SqlError, Row};
3use sos_core::UtcDateTime;
4use sos_system_messages::SysMessage;
5use sql_query_builder as sql;
6use std::ops::Deref;
7use urn::Urn;
8
9/// SystemMessage row from the database.
10#[doc(hidden)]
11#[derive(Debug, Default)]
12pub struct SystemMessageRow {
13    pub row_id: i64,
14    created_at: String,
15    modified_at: String,
16    key: String,
17    json_data: String,
18}
19
20impl<'a> TryFrom<&Row<'a>> for SystemMessageRow {
21    type Error = SqlError;
22    fn try_from(row: &Row<'a>) -> std::result::Result<Self, Self::Error> {
23        Ok(SystemMessageRow {
24            row_id: row.get(0)?,
25            created_at: row.get(1)?,
26            modified_at: row.get(2)?,
27            key: row.get(3)?,
28            json_data: row.get(4)?,
29        })
30    }
31}
32
33impl TryFrom<SystemMessageRow> for (Urn, SysMessage) {
34    type Error = crate::Error;
35    fn try_from(
36        row: SystemMessageRow,
37    ) -> std::result::Result<Self, Self::Error> {
38        Ok((row.key.parse()?, serde_json::from_str(&row.json_data)?))
39    }
40}
41
42impl TryFrom<(Urn, SysMessage)> for SystemMessageRow {
43    type Error = crate::Error;
44    fn try_from(
45        value: (Urn, SysMessage),
46    ) -> std::result::Result<Self, Self::Error> {
47        Ok(Self {
48            created_at: UtcDateTime::default().to_rfc3339()?,
49            modified_at: UtcDateTime::default().to_rfc3339()?,
50            key: value.0.to_string(),
51            json_data: serde_json::to_string(&value.1)?,
52            ..Default::default()
53        })
54    }
55}
56
57/// SystemMessage entity.
58pub struct SystemMessageEntity<'conn, C>
59where
60    C: Deref<Target = Connection>,
61{
62    conn: &'conn C,
63}
64
65impl<'conn, C> SystemMessageEntity<'conn, C>
66where
67    C: Deref<Target = Connection>,
68{
69    /// Create a new server entity.
70    pub fn new(conn: &'conn C) -> Self {
71        Self { conn }
72    }
73
74    /// Load system messages for an account.
75    pub fn load_system_messages(
76        &self,
77        account_id: i64,
78    ) -> Result<Vec<SystemMessageRow>> {
79        let query = sql::Select::new()
80            .select(
81                r#"
82                    system_message_id,
83                    created_at,
84                    modified_at,
85                    key,
86                    json_data
87                "#,
88            )
89            .from("system_messages")
90            .where_clause("account_id = ?1");
91        let mut stmt = self.conn.prepare_cached(&query.as_string())?;
92
93        fn convert_row(row: &Row<'_>) -> Result<SystemMessageRow> {
94            Ok(row.try_into()?)
95        }
96
97        let rows = stmt.query_and_then([account_id], |row| {
98            Ok::<_, crate::Error>(convert_row(row)?)
99        })?;
100        let mut messages = Vec::new();
101        for row in rows {
102            messages.push(row?);
103        }
104        Ok(messages)
105    }
106
107    /// Update the is_read flag for a system message.
108    pub fn mark_system_message(
109        &self,
110        account_id: i64,
111        key: &str,
112        is_read: bool,
113    ) -> Result<()> {
114        let modified_at = UtcDateTime::default().to_rfc3339()?;
115        let query = sql::Update::new()
116            .update("system_messages")
117            .set(
118                "
119                modified_at = ?1,
120                json_data = json_replace (json_data, '$.isRead', ?2)
121            ",
122            )
123            .where_clause("account_id = ?3")
124            .where_and("key = ?4");
125        let mut stmt = self.conn.prepare_cached(&query.as_string())?;
126        stmt.execute((modified_at, is_read, account_id, key))?;
127        Ok(())
128    }
129
130    /// Delete a system message for an account.
131    pub fn delete_system_message(
132        &self,
133        account_id: i64,
134        key: &str,
135    ) -> std::result::Result<(), SqlError> {
136        let query = sql::Delete::new()
137            .delete_from("system_messages")
138            .where_clause("account_id = ?1")
139            .where_and("key = ?2");
140        let mut stmt = self.conn.prepare_cached(&query.as_string())?;
141        stmt.execute((account_id, key))?;
142        Ok(())
143    }
144
145    /// Delete system messages for an account.
146    pub fn delete_system_messages(
147        &self,
148        account_id: i64,
149    ) -> std::result::Result<(), SqlError> {
150        let query = sql::Delete::new()
151            .delete_from("system_messages")
152            .where_clause("account_id = ?1");
153        let mut stmt = self.conn.prepare_cached(&query.as_string())?;
154        stmt.execute([account_id])?;
155        Ok(())
156    }
157
158    /// Create system message in the database.
159    pub fn insert_system_message(
160        &self,
161        account_id: i64,
162        row: &SystemMessageRow,
163    ) -> std::result::Result<(), SqlError> {
164        let query = sql::Insert::new()
165            .insert_into(
166                r#"
167                system_messages
168                (
169                    account_id,
170                    created_at,
171                    modified_at,
172                    key,
173                    json_data
174                )
175                "#,
176            )
177            .values("(?1, ?2, ?3, ?4, ?5)");
178        let mut stmt = self.conn.prepare_cached(&query.as_string())?;
179        stmt.execute((
180            account_id,
181            &row.created_at,
182            &row.modified_at,
183            &row.key,
184            &row.json_data,
185        ))?;
186        Ok(())
187    }
188
189    /// Create system messages in the database.
190    pub fn insert_system_messages(
191        &self,
192        account_id: i64,
193        system_messages: &[SystemMessageRow],
194    ) -> std::result::Result<(), SqlError> {
195        for row in system_messages {
196            self.insert_system_message(account_id, row)?;
197        }
198        Ok(())
199    }
200}