]> Untitled Git - lemmy.git/blob - lemmy_db/src/aggregates/user_aggregates.rs
622bce113d7309a29df9e8fe99ee8896aae8cc03
[lemmy.git] / lemmy_db / src / aggregates / user_aggregates.rs
1 use crate::schema::user_aggregates;
2 use diesel::{result::Error, *};
3 use serde::Serialize;
4
5 #[derive(Queryable, Associations, Identifiable, PartialEq, Debug, Serialize, Clone)]
6 #[table_name = "user_aggregates"]
7 pub struct UserAggregates {
8   pub id: i32,
9   pub user_id: i32,
10   pub post_count: i64,
11   pub post_score: i64,
12   pub comment_count: i64,
13   pub comment_score: i64,
14 }
15
16 impl UserAggregates {
17   pub fn read(conn: &PgConnection, user_id: i32) -> Result<Self, Error> {
18     user_aggregates::table
19       .filter(user_aggregates::user_id.eq(user_id))
20       .first::<Self>(conn)
21   }
22 }
23
24 #[cfg(test)]
25 mod tests {
26   use crate::{
27     aggregates::user_aggregates::UserAggregates,
28     comment::{Comment, CommentForm, CommentLike, CommentLikeForm},
29     community::{Community, CommunityForm},
30     post::{Post, PostForm, PostLike, PostLikeForm},
31     tests::establish_unpooled_connection,
32     user::{UserForm, User_},
33     Crud,
34     Likeable,
35     ListingType,
36     SortType,
37   };
38
39   #[test]
40   fn test_crud() {
41     let conn = establish_unpooled_connection();
42
43     let new_user = UserForm {
44       name: "thommy_user_agg".into(),
45       preferred_username: None,
46       password_encrypted: "nope".into(),
47       email: None,
48       matrix_user_id: None,
49       avatar: None,
50       banner: None,
51       admin: false,
52       banned: Some(false),
53       published: None,
54       updated: None,
55       show_nsfw: false,
56       theme: "browser".into(),
57       default_sort_type: SortType::Hot as i16,
58       default_listing_type: ListingType::Subscribed as i16,
59       lang: "browser".into(),
60       show_avatars: true,
61       send_notifications_to_email: false,
62       actor_id: None,
63       bio: None,
64       local: true,
65       private_key: None,
66       public_key: None,
67       last_refreshed_at: None,
68     };
69
70     let inserted_user = User_::create(&conn, &new_user).unwrap();
71
72     let another_user = UserForm {
73       name: "jerry_user_agg".into(),
74       preferred_username: None,
75       password_encrypted: "nope".into(),
76       email: None,
77       matrix_user_id: None,
78       avatar: None,
79       banner: None,
80       admin: false,
81       banned: Some(false),
82       published: None,
83       updated: None,
84       show_nsfw: false,
85       theme: "browser".into(),
86       default_sort_type: SortType::Hot as i16,
87       default_listing_type: ListingType::Subscribed as i16,
88       lang: "browser".into(),
89       show_avatars: true,
90       send_notifications_to_email: false,
91       actor_id: None,
92       bio: None,
93       local: true,
94       private_key: None,
95       public_key: None,
96       last_refreshed_at: None,
97     };
98
99     let another_inserted_user = User_::create(&conn, &another_user).unwrap();
100
101     let new_community = CommunityForm {
102       name: "TIL_site_agg".into(),
103       creator_id: inserted_user.id,
104       title: "nada".to_owned(),
105       description: None,
106       category_id: 1,
107       nsfw: false,
108       removed: None,
109       deleted: None,
110       updated: None,
111       actor_id: None,
112       local: true,
113       private_key: None,
114       public_key: None,
115       last_refreshed_at: None,
116       published: None,
117       icon: None,
118       banner: None,
119     };
120
121     let inserted_community = Community::create(&conn, &new_community).unwrap();
122
123     let new_post = PostForm {
124       name: "A test post".into(),
125       url: None,
126       body: None,
127       creator_id: inserted_user.id,
128       community_id: inserted_community.id,
129       removed: None,
130       deleted: None,
131       locked: None,
132       stickied: None,
133       nsfw: false,
134       updated: None,
135       embed_title: None,
136       embed_description: None,
137       embed_html: None,
138       thumbnail_url: None,
139       ap_id: None,
140       local: true,
141       published: None,
142     };
143
144     let inserted_post = Post::create(&conn, &new_post).unwrap();
145
146     let post_like = PostLikeForm {
147       post_id: inserted_post.id,
148       user_id: inserted_user.id,
149       score: 1,
150     };
151
152     let _inserted_post_like = PostLike::like(&conn, &post_like).unwrap();
153
154     let comment_form = CommentForm {
155       content: "A test comment".into(),
156       creator_id: inserted_user.id,
157       post_id: inserted_post.id,
158       removed: None,
159       deleted: None,
160       read: None,
161       parent_id: None,
162       published: None,
163       updated: None,
164       ap_id: None,
165       local: true,
166     };
167
168     let inserted_comment = Comment::create(&conn, &comment_form).unwrap();
169
170     let comment_like = CommentLikeForm {
171       comment_id: inserted_comment.id,
172       user_id: inserted_user.id,
173       post_id: inserted_post.id,
174       score: 1,
175     };
176
177     let _inserted_comment_like = CommentLike::like(&conn, &comment_like).unwrap();
178
179     let child_comment_form = CommentForm {
180       content: "A test comment".into(),
181       creator_id: inserted_user.id,
182       post_id: inserted_post.id,
183       removed: None,
184       deleted: None,
185       read: None,
186       parent_id: Some(inserted_comment.id),
187       published: None,
188       updated: None,
189       ap_id: None,
190       local: true,
191     };
192
193     let inserted_child_comment = Comment::create(&conn, &child_comment_form).unwrap();
194
195     let child_comment_like = CommentLikeForm {
196       comment_id: inserted_child_comment.id,
197       user_id: another_inserted_user.id,
198       post_id: inserted_post.id,
199       score: 1,
200     };
201
202     let _inserted_child_comment_like = CommentLike::like(&conn, &child_comment_like).unwrap();
203
204     let user_aggregates_before_delete = UserAggregates::read(&conn, inserted_user.id).unwrap();
205
206     assert_eq!(1, user_aggregates_before_delete.post_count);
207     assert_eq!(1, user_aggregates_before_delete.post_score);
208     assert_eq!(2, user_aggregates_before_delete.comment_count);
209     assert_eq!(2, user_aggregates_before_delete.comment_score);
210
211     // Remove a post like
212     PostLike::remove(&conn, inserted_user.id, inserted_post.id).unwrap();
213     let after_post_like_remove = UserAggregates::read(&conn, inserted_user.id).unwrap();
214     assert_eq!(0, after_post_like_remove.post_score);
215
216     // Remove a parent comment (the scores should also be removed)
217     Comment::delete(&conn, inserted_comment.id).unwrap();
218     let after_parent_comment_delete = UserAggregates::read(&conn, inserted_user.id).unwrap();
219     assert_eq!(0, after_parent_comment_delete.comment_count);
220     assert_eq!(0, after_parent_comment_delete.comment_score);
221
222     // This should delete all the associated rows, and fire triggers
223     let user_num_deleted = User_::delete(&conn, inserted_user.id).unwrap();
224     assert_eq!(1, user_num_deleted);
225     User_::delete(&conn, another_inserted_user.id).unwrap();
226
227     // Should be none found
228     let after_delete = UserAggregates::read(&conn, inserted_user.id);
229     assert!(after_delete.is_err());
230   }
231 }