Skip to main content

autter_core/database/
audit_log.rs

1use crate::DataManager;
2use crate::model::{AuditLogEntry, Error, Result, User, UserPermission};
3use oiseau::PostgresRow;
4use oiseau::cache::Cache;
5use oiseau::{execute, get, params, query_rows};
6use tetratto_core2::{auto_method, model::id::Id};
7
8impl DataManager {
9    /// Get an [`AuditLogEntry`] from an SQL row.
10    pub(crate) fn get_audit_log_entry_from_row(x: &PostgresRow) -> AuditLogEntry {
11        AuditLogEntry {
12            id: Id::deserialize(&get!(x->0(String))),
13            created: get!(x->1(i64)) as u128,
14            moderator: Id::Legacy(get!(x->2(i64)) as usize),
15            content: get!(x->3(String)),
16        }
17    }
18
19    auto_method!(get_audit_log_entry_by_id(usize as i64)@get_audit_log_entry_from_row -> "SELECT * FROM a_audit_log WHERE id = $1" --name="audit log entry" --returns=AuditLogEntry --cache-key-tmpl="srmp.audit_log:{}");
20
21    /// Get all audit log entries (paginated).
22    ///
23    /// # Arguments
24    /// * `batch` - the limit of items in each page
25    /// * `page` - the page number
26    pub async fn get_audit_log_entries(
27        &self,
28        batch: usize,
29        page: usize,
30    ) -> Result<Vec<AuditLogEntry>> {
31        let conn = match self.0.connect().await {
32            Ok(c) => c,
33            Err(e) => return Err(Error::DatabaseConnection(e.to_string())),
34        };
35
36        let res = query_rows!(
37            &conn,
38            "SELECT * FROM a_audit_log ORDER BY created DESC LIMIT $1 OFFSET $2",
39            &[&(batch as i64), &((page * batch) as i64)],
40            |x| { Self::get_audit_log_entry_from_row(x) }
41        );
42
43        if res.is_err() {
44            return Err(Error::GeneralNotFound("audit log entry".to_string()));
45        }
46
47        Ok(res.unwrap())
48    }
49
50    /// Create a new audit log entry in the database.
51    ///
52    /// # Arguments
53    /// * `data` - a mock [`AuditLogEntry`] object to insert
54    pub async fn create_audit_log_entry(&self, data: AuditLogEntry) -> Result<()> {
55        let conn = match self.0.connect().await {
56            Ok(c) => c,
57            Err(e) => return Err(Error::DatabaseConnection(e.to_string())),
58        };
59
60        let res = execute!(
61            &conn,
62            "INSERT INTO a_audit_log VALUES ($1, $2, $3, $4)",
63            params![
64                &data.id.printable(),
65                &(data.created as i64),
66                &(data.moderator.as_usize() as i64),
67                &data.content.as_str(),
68            ]
69        );
70
71        if let Err(e) = res {
72            return Err(Error::DatabaseError(e.to_string()));
73        }
74
75        // return
76        Ok(())
77    }
78
79    pub async fn delete_audit_log_entry(&self, id: &Id, user: User) -> Result<()> {
80        if !user.permissions.contains(&UserPermission::ManageAuditLog) {
81            return Err(Error::NotAllowed);
82        }
83
84        let conn = match self.0.connect().await {
85            Ok(c) => c,
86            Err(e) => return Err(Error::DatabaseConnection(e.to_string())),
87        };
88
89        let res = execute!(
90            &conn,
91            "DELETE FROM a_audit_log WHERE id = $1",
92            &[&id.printable()]
93        );
94
95        if let Err(e) = res {
96            return Err(Error::DatabaseError(e.to_string()));
97        }
98
99        self.0.1.remove(format!("srmp.audit_log:{}", id)).await;
100
101        // return
102        Ok(())
103    }
104}