Skip to main content

tetratto_core/database/
post_views.rs

1use oiseau::cache::Cache;
2use crate::model::{Error, Result, auth::User, communities::PostView};
3use crate::{auto_method, DataManager};
4use oiseau::{execute, get, params, query_row, PostgresRow};
5
6impl DataManager {
7    /// Get a [`PostView`] from an SQL row.
8    pub(crate) fn get_post_view_from_row(x: &PostgresRow) -> PostView {
9        PostView {
10            id: get!(x->0(i64)) as usize,
11            created: get!(x->1(i64)) as usize,
12            owner: get!(x->2(i64)) as usize,
13            post: get!(x->3(i64)) as usize,
14        }
15    }
16
17    auto_method!(get_post_view_by_id()@get_post_view_from_row -> "SELECT * FROM post_views WHERE id = $1" --name="post_view" --returns=PostView --cache-key-tmpl="atto.post_view:{}");
18
19    /// Get a post view by `owner` and `post`.
20    pub async fn get_post_view_by_owner_post(&self, owner: usize, post: usize) -> Result<PostView> {
21        let conn = match self.0.connect().await {
22            Ok(c) => c,
23            Err(e) => return Err(Error::DatabaseConnection(e.to_string())),
24        };
25
26        let res = query_row!(
27            &conn,
28            "SELECT * FROM post_views WHERE owner = $1 AND post = $2 LIMIT 1",
29            &[&(owner as i64), &(post as i64)],
30            |x| { Ok(Self::get_post_view_from_row(x)) }
31        );
32
33        if res.is_err() {
34            return Err(Error::GeneralNotFound("post view".to_string()));
35        }
36
37        Ok(res.unwrap())
38    }
39
40    /// Create a new post view in the database.
41    ///
42    /// # Arguments
43    /// * `data` - a mock [`PostView`] object to insert
44    pub async fn create_post_view(&self, data: PostView) -> Result<usize> {
45        let conn = match self.0.connect().await {
46            Ok(c) => c,
47            Err(e) => return Err(Error::DatabaseConnection(e.to_string())),
48        };
49
50        let res = execute!(
51            &conn,
52            "INSERT INTO post_views VALUES ($1, $2, $3, $4)",
53            params![
54                &(data.id as i64),
55                &(data.created as i64),
56                &(data.owner as i64),
57                &(data.post as i64),
58            ]
59        );
60
61        if let Err(e) = res {
62            return Err(Error::DatabaseError(e.to_string()));
63        }
64
65        // incr post views count
66        self.incr_post_views(data.post).await?;
67
68        // return
69        Ok(data.id)
70    }
71
72    pub async fn delete_post_view(&self, id: usize, user: &User) -> Result<()> {
73        let y = self.get_post_view_by_id(id).await?;
74
75        if user.id != y.owner {
76            return Err(Error::NotAllowed);
77        }
78
79        let conn = match self.0.connect().await {
80            Ok(c) => c,
81            Err(e) => return Err(Error::DatabaseConnection(e.to_string())),
82        };
83
84        let res = execute!(
85            &conn,
86            "DELETE FROM post_views WHERE id = $1",
87            &[&(id as i64)]
88        );
89
90        if let Err(e) = res {
91            return Err(Error::DatabaseError(e.to_string()));
92        }
93
94        self.0.1.remove(format!("atto.post_view:{}", id)).await;
95
96        // decr post views count
97        self.decr_post_views(y.post).await?;
98
99        // return
100        Ok(())
101    }
102}