]> Untitled Git - lemmy.git/blob - server/src/db/comment.rs
Merge remote-tracking branch 'upstream/master'
[lemmy.git] / server / src / db / comment.rs
1 use super::post::Post;
2 use super::*;
3 use crate::schema::{comment, comment_like, comment_saved};
4
5 // WITH RECURSIVE MyTree AS (
6 //     SELECT * FROM comment WHERE parent_id IS NULL
7 //     UNION ALL
8 //     SELECT m.* FROM comment AS m JOIN MyTree AS t ON m.parent_id = t.id
9 // )
10 // SELECT * FROM MyTree;
11
12 #[derive(Queryable, Associations, Identifiable, PartialEq, Debug, Serialize, Deserialize)]
13 #[belongs_to(Post)]
14 #[table_name = "comment"]
15 pub struct Comment {
16   pub id: i32,
17   pub creator_id: i32,
18   pub post_id: i32,
19   pub parent_id: Option<i32>,
20   pub content: String,
21   pub removed: bool,
22   pub read: bool,
23   pub published: chrono::NaiveDateTime,
24   pub updated: Option<chrono::NaiveDateTime>,
25   pub deleted: bool,
26 }
27
28 #[derive(Insertable, AsChangeset, Clone)]
29 #[table_name = "comment"]
30 pub struct CommentForm {
31   pub creator_id: i32,
32   pub post_id: i32,
33   pub parent_id: Option<i32>,
34   pub content: String,
35   pub removed: Option<bool>,
36   pub read: Option<bool>,
37   pub updated: Option<chrono::NaiveDateTime>,
38   pub deleted: Option<bool>,
39 }
40
41 impl Crud<CommentForm> for Comment {
42   fn read(conn: &PgConnection, comment_id: i32) -> Result<Self, Error> {
43     use crate::schema::comment::dsl::*;
44     comment.find(comment_id).first::<Self>(conn)
45   }
46
47   fn delete(conn: &PgConnection, comment_id: i32) -> Result<usize, Error> {
48     use crate::schema::comment::dsl::*;
49     diesel::delete(comment.find(comment_id)).execute(conn)
50   }
51
52   fn create(conn: &PgConnection, comment_form: &CommentForm) -> Result<Self, Error> {
53     use crate::schema::comment::dsl::*;
54     insert_into(comment)
55       .values(comment_form)
56       .get_result::<Self>(conn)
57   }
58
59   fn update(
60     conn: &PgConnection,
61     comment_id: i32,
62     comment_form: &CommentForm,
63   ) -> Result<Self, Error> {
64     use crate::schema::comment::dsl::*;
65     diesel::update(comment.find(comment_id))
66       .set(comment_form)
67       .get_result::<Self>(conn)
68   }
69 }
70
71 #[derive(Identifiable, Queryable, Associations, PartialEq, Debug, Clone)]
72 #[belongs_to(Comment)]
73 #[table_name = "comment_like"]
74 pub struct CommentLike {
75   pub id: i32,
76   pub user_id: i32,
77   pub comment_id: i32,
78   pub post_id: i32,
79   pub score: i16,
80   pub published: chrono::NaiveDateTime,
81 }
82
83 #[derive(Insertable, AsChangeset, Clone)]
84 #[table_name = "comment_like"]
85 pub struct CommentLikeForm {
86   pub user_id: i32,
87   pub comment_id: i32,
88   pub post_id: i32,
89   pub score: i16,
90 }
91
92 impl Likeable<CommentLikeForm> for CommentLike {
93   fn read(conn: &PgConnection, comment_id_from: i32) -> Result<Vec<Self>, Error> {
94     use crate::schema::comment_like::dsl::*;
95     comment_like
96       .filter(comment_id.eq(comment_id_from))
97       .load::<Self>(conn)
98   }
99
100   fn like(conn: &PgConnection, comment_like_form: &CommentLikeForm) -> Result<Self, Error> {
101     use crate::schema::comment_like::dsl::*;
102     insert_into(comment_like)
103       .values(comment_like_form)
104       .get_result::<Self>(conn)
105   }
106   fn remove(conn: &PgConnection, comment_like_form: &CommentLikeForm) -> Result<usize, Error> {
107     use crate::schema::comment_like::dsl::*;
108     diesel::delete(
109       comment_like
110         .filter(comment_id.eq(comment_like_form.comment_id))
111         .filter(user_id.eq(comment_like_form.user_id)),
112     )
113     .execute(conn)
114   }
115 }
116
117 impl CommentLike {
118   pub fn from_post(conn: &PgConnection, post_id_from: i32) -> Result<Vec<Self>, Error> {
119     use crate::schema::comment_like::dsl::*;
120     comment_like
121       .filter(post_id.eq(post_id_from))
122       .load::<Self>(conn)
123   }
124 }
125
126 #[derive(Identifiable, Queryable, Associations, PartialEq, Debug)]
127 #[belongs_to(Comment)]
128 #[table_name = "comment_saved"]
129 pub struct CommentSaved {
130   pub id: i32,
131   pub comment_id: i32,
132   pub user_id: i32,
133   pub published: chrono::NaiveDateTime,
134 }
135
136 #[derive(Insertable, AsChangeset, Clone)]
137 #[table_name = "comment_saved"]
138 pub struct CommentSavedForm {
139   pub comment_id: i32,
140   pub user_id: i32,
141 }
142
143 impl Saveable<CommentSavedForm> for CommentSaved {
144   fn save(conn: &PgConnection, comment_saved_form: &CommentSavedForm) -> Result<Self, Error> {
145     use crate::schema::comment_saved::dsl::*;
146     insert_into(comment_saved)
147       .values(comment_saved_form)
148       .get_result::<Self>(conn)
149   }
150   fn unsave(conn: &PgConnection, comment_saved_form: &CommentSavedForm) -> Result<usize, Error> {
151     use crate::schema::comment_saved::dsl::*;
152     diesel::delete(
153       comment_saved
154         .filter(comment_id.eq(comment_saved_form.comment_id))
155         .filter(user_id.eq(comment_saved_form.user_id)),
156     )
157     .execute(conn)
158   }
159 }
160
161 #[cfg(test)]
162 mod tests {
163   use super::super::community::*;
164   use super::super::post::*;
165   use super::super::user::*;
166   use super::*;
167   #[test]
168   fn test_crud() {
169     let conn = establish_unpooled_connection();
170
171     let new_user = UserForm {
172       name: "terry".into(),
173       fedi_name: "rrf".into(),
174       preferred_username: None,
175       password_encrypted: "nope".into(),
176       email: None,
177       matrix_user_id: None,
178       avatar: None,
179       admin: false,
180       banned: false,
181       updated: None,
182       show_nsfw: false,
183       theme: "darkly".into(),
184       default_sort_type: SortType::Hot as i16,
185       default_listing_type: ListingType::Subscribed as i16,
186       lang: "browser".into(),
187       show_avatars: true,
188       send_notifications_to_email: false,
189     };
190
191     let inserted_user = User_::create(&conn, &new_user).unwrap();
192
193     let new_community = CommunityForm {
194       name: "test community".to_string(),
195       title: "nada".to_owned(),
196       description: None,
197       category_id: 1,
198       creator_id: inserted_user.id,
199       removed: None,
200       deleted: None,
201       updated: None,
202       nsfw: false,
203     };
204
205     let inserted_community = Community::create(&conn, &new_community).unwrap();
206
207     let new_post = PostForm {
208       name: "A test post".into(),
209       creator_id: inserted_user.id,
210       url: None,
211       body: None,
212       community_id: inserted_community.id,
213       removed: None,
214       deleted: None,
215       locked: None,
216       stickied: None,
217       updated: None,
218       nsfw: false,
219     };
220
221     let inserted_post = Post::create(&conn, &new_post).unwrap();
222
223     let comment_form = CommentForm {
224       content: "A test comment".into(),
225       creator_id: inserted_user.id,
226       post_id: inserted_post.id,
227       removed: None,
228       deleted: None,
229       read: None,
230       parent_id: None,
231       updated: None,
232     };
233
234     let inserted_comment = Comment::create(&conn, &comment_form).unwrap();
235
236     let expected_comment = Comment {
237       id: inserted_comment.id,
238       content: "A test comment".into(),
239       creator_id: inserted_user.id,
240       post_id: inserted_post.id,
241       removed: false,
242       deleted: false,
243       read: false,
244       parent_id: None,
245       published: inserted_comment.published,
246       updated: None,
247     };
248
249     let child_comment_form = CommentForm {
250       content: "A child comment".into(),
251       creator_id: inserted_user.id,
252       post_id: inserted_post.id,
253       parent_id: Some(inserted_comment.id),
254       removed: None,
255       deleted: None,
256       read: None,
257       updated: None,
258     };
259
260     let inserted_child_comment = Comment::create(&conn, &child_comment_form).unwrap();
261
262     // Comment Like
263     let comment_like_form = CommentLikeForm {
264       comment_id: inserted_comment.id,
265       post_id: inserted_post.id,
266       user_id: inserted_user.id,
267       score: 1,
268     };
269
270     let inserted_comment_like = CommentLike::like(&conn, &comment_like_form).unwrap();
271
272     let expected_comment_like = CommentLike {
273       id: inserted_comment_like.id,
274       comment_id: inserted_comment.id,
275       post_id: inserted_post.id,
276       user_id: inserted_user.id,
277       published: inserted_comment_like.published,
278       score: 1,
279     };
280
281     // Comment Saved
282     let comment_saved_form = CommentSavedForm {
283       comment_id: inserted_comment.id,
284       user_id: inserted_user.id,
285     };
286
287     let inserted_comment_saved = CommentSaved::save(&conn, &comment_saved_form).unwrap();
288
289     let expected_comment_saved = CommentSaved {
290       id: inserted_comment_saved.id,
291       comment_id: inserted_comment.id,
292       user_id: inserted_user.id,
293       published: inserted_comment_saved.published,
294     };
295
296     let read_comment = Comment::read(&conn, inserted_comment.id).unwrap();
297     let updated_comment = Comment::update(&conn, inserted_comment.id, &comment_form).unwrap();
298     let like_removed = CommentLike::remove(&conn, &comment_like_form).unwrap();
299     let saved_removed = CommentSaved::unsave(&conn, &comment_saved_form).unwrap();
300     let num_deleted = Comment::delete(&conn, inserted_comment.id).unwrap();
301     Comment::delete(&conn, inserted_child_comment.id).unwrap();
302     Post::delete(&conn, inserted_post.id).unwrap();
303     Community::delete(&conn, inserted_community.id).unwrap();
304     User_::delete(&conn, inserted_user.id).unwrap();
305
306     assert_eq!(expected_comment, read_comment);
307     assert_eq!(expected_comment, inserted_comment);
308     assert_eq!(expected_comment, updated_comment);
309     assert_eq!(expected_comment_like, inserted_comment_like);
310     assert_eq!(expected_comment_saved, inserted_comment_saved);
311     assert_eq!(
312       expected_comment.id,
313       inserted_child_comment.parent_id.unwrap()
314     );
315     assert_eq!(1, like_removed);
316     assert_eq!(1, saved_removed);
317     assert_eq!(1, num_deleted);
318   }
319 }