Skip to main content

tetratto_core/database/
profile_views.rs

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