]> Untitled Git - lemmy.git/blob - crates/db_queries/src/source/post.rs
Merge pull request #1328 from LemmyNet/move_views_to_diesel
[lemmy.git] / crates / db_queries / src / source / post.rs
1 use crate::{ApubObject, Crud, Likeable, Readable, Saveable};
2 use diesel::{dsl::*, result::Error, *};
3 use lemmy_db_schema::{
4   naive_now,
5   source::post::{
6     Post,
7     PostForm,
8     PostLike,
9     PostLikeForm,
10     PostRead,
11     PostReadForm,
12     PostSaved,
13     PostSavedForm,
14   },
15 };
16
17 impl Crud<PostForm> for Post {
18   fn read(conn: &PgConnection, post_id: i32) -> Result<Self, Error> {
19     use lemmy_db_schema::schema::post::dsl::*;
20     post.find(post_id).first::<Self>(conn)
21   }
22
23   fn delete(conn: &PgConnection, post_id: i32) -> Result<usize, Error> {
24     use lemmy_db_schema::schema::post::dsl::*;
25     diesel::delete(post.find(post_id)).execute(conn)
26   }
27
28   fn create(conn: &PgConnection, new_post: &PostForm) -> Result<Self, Error> {
29     use lemmy_db_schema::schema::post::dsl::*;
30     insert_into(post).values(new_post).get_result::<Self>(conn)
31   }
32
33   fn update(conn: &PgConnection, post_id: i32, new_post: &PostForm) -> Result<Self, Error> {
34     use lemmy_db_schema::schema::post::dsl::*;
35     diesel::update(post.find(post_id))
36       .set(new_post)
37       .get_result::<Self>(conn)
38   }
39 }
40
41 pub trait Post_ {
42   //fn read(conn: &PgConnection, post_id: i32) -> Result<Post, Error>;
43   fn list_for_community(conn: &PgConnection, the_community_id: i32) -> Result<Vec<Post>, Error>;
44   fn update_ap_id(conn: &PgConnection, post_id: i32, apub_id: String) -> Result<Post, Error>;
45   fn permadelete_for_creator(conn: &PgConnection, for_creator_id: i32) -> Result<Vec<Post>, Error>;
46   fn update_deleted(conn: &PgConnection, post_id: i32, new_deleted: bool) -> Result<Post, Error>;
47   fn update_removed(conn: &PgConnection, post_id: i32, new_removed: bool) -> Result<Post, Error>;
48   fn update_removed_for_creator(
49     conn: &PgConnection,
50     for_creator_id: i32,
51     for_community_id: Option<i32>,
52     new_removed: bool,
53   ) -> Result<Vec<Post>, Error>;
54   fn update_locked(conn: &PgConnection, post_id: i32, new_locked: bool) -> Result<Post, Error>;
55   fn update_stickied(conn: &PgConnection, post_id: i32, new_stickied: bool) -> Result<Post, Error>;
56   fn is_post_creator(user_id: i32, post_creator_id: i32) -> bool;
57 }
58
59 impl Post_ for Post {
60   fn list_for_community(conn: &PgConnection, the_community_id: i32) -> Result<Vec<Self>, Error> {
61     use lemmy_db_schema::schema::post::dsl::*;
62     post
63       .filter(community_id.eq(the_community_id))
64       .then_order_by(published.desc())
65       .then_order_by(stickied.desc())
66       .limit(20)
67       .load::<Self>(conn)
68   }
69
70   fn update_ap_id(conn: &PgConnection, post_id: i32, apub_id: String) -> Result<Self, Error> {
71     use lemmy_db_schema::schema::post::dsl::*;
72
73     diesel::update(post.find(post_id))
74       .set(ap_id.eq(apub_id))
75       .get_result::<Self>(conn)
76   }
77
78   fn permadelete_for_creator(conn: &PgConnection, for_creator_id: i32) -> Result<Vec<Self>, Error> {
79     use lemmy_db_schema::schema::post::dsl::*;
80
81     let perma_deleted = "*Permananently Deleted*";
82     let perma_deleted_url = "https://deleted.com";
83
84     diesel::update(post.filter(creator_id.eq(for_creator_id)))
85       .set((
86         name.eq(perma_deleted),
87         url.eq(perma_deleted_url),
88         body.eq(perma_deleted),
89         deleted.eq(true),
90         updated.eq(naive_now()),
91       ))
92       .get_results::<Self>(conn)
93   }
94
95   fn update_deleted(conn: &PgConnection, post_id: i32, new_deleted: bool) -> Result<Self, Error> {
96     use lemmy_db_schema::schema::post::dsl::*;
97     diesel::update(post.find(post_id))
98       .set((deleted.eq(new_deleted), updated.eq(naive_now())))
99       .get_result::<Self>(conn)
100   }
101
102   fn update_removed(conn: &PgConnection, post_id: i32, new_removed: bool) -> Result<Self, Error> {
103     use lemmy_db_schema::schema::post::dsl::*;
104     diesel::update(post.find(post_id))
105       .set((removed.eq(new_removed), updated.eq(naive_now())))
106       .get_result::<Self>(conn)
107   }
108
109   fn update_removed_for_creator(
110     conn: &PgConnection,
111     for_creator_id: i32,
112     for_community_id: Option<i32>,
113     new_removed: bool,
114   ) -> Result<Vec<Self>, Error> {
115     use lemmy_db_schema::schema::post::dsl::*;
116
117     let mut update = diesel::update(post).into_boxed();
118     update = update.filter(creator_id.eq(for_creator_id));
119
120     if let Some(for_community_id) = for_community_id {
121       update = update.filter(community_id.eq(for_community_id));
122     }
123
124     update
125       .set((removed.eq(new_removed), updated.eq(naive_now())))
126       .get_results::<Self>(conn)
127   }
128
129   fn update_locked(conn: &PgConnection, post_id: i32, new_locked: bool) -> Result<Self, Error> {
130     use lemmy_db_schema::schema::post::dsl::*;
131     diesel::update(post.find(post_id))
132       .set(locked.eq(new_locked))
133       .get_result::<Self>(conn)
134   }
135
136   fn update_stickied(conn: &PgConnection, post_id: i32, new_stickied: bool) -> Result<Self, Error> {
137     use lemmy_db_schema::schema::post::dsl::*;
138     diesel::update(post.find(post_id))
139       .set(stickied.eq(new_stickied))
140       .get_result::<Self>(conn)
141   }
142
143   fn is_post_creator(user_id: i32, post_creator_id: i32) -> bool {
144     user_id == post_creator_id
145   }
146 }
147
148 impl ApubObject<PostForm> for Post {
149   fn read_from_apub_id(conn: &PgConnection, object_id: &str) -> Result<Self, Error> {
150     use lemmy_db_schema::schema::post::dsl::*;
151     post.filter(ap_id.eq(object_id)).first::<Self>(conn)
152   }
153
154   fn upsert(conn: &PgConnection, post_form: &PostForm) -> Result<Post, Error> {
155     use lemmy_db_schema::schema::post::dsl::*;
156     insert_into(post)
157       .values(post_form)
158       .on_conflict(ap_id)
159       .do_update()
160       .set(post_form)
161       .get_result::<Self>(conn)
162   }
163 }
164
165 impl Likeable<PostLikeForm> for PostLike {
166   fn like(conn: &PgConnection, post_like_form: &PostLikeForm) -> Result<Self, Error> {
167     use lemmy_db_schema::schema::post_like::dsl::*;
168     insert_into(post_like)
169       .values(post_like_form)
170       .on_conflict((post_id, user_id))
171       .do_update()
172       .set(post_like_form)
173       .get_result::<Self>(conn)
174   }
175   fn remove(conn: &PgConnection, user_id: i32, post_id: i32) -> Result<usize, Error> {
176     use lemmy_db_schema::schema::post_like::dsl;
177     diesel::delete(
178       dsl::post_like
179         .filter(dsl::post_id.eq(post_id))
180         .filter(dsl::user_id.eq(user_id)),
181     )
182     .execute(conn)
183   }
184 }
185
186 impl Saveable<PostSavedForm> for PostSaved {
187   fn save(conn: &PgConnection, post_saved_form: &PostSavedForm) -> Result<Self, Error> {
188     use lemmy_db_schema::schema::post_saved::dsl::*;
189     insert_into(post_saved)
190       .values(post_saved_form)
191       .on_conflict((post_id, user_id))
192       .do_update()
193       .set(post_saved_form)
194       .get_result::<Self>(conn)
195   }
196   fn unsave(conn: &PgConnection, post_saved_form: &PostSavedForm) -> Result<usize, Error> {
197     use lemmy_db_schema::schema::post_saved::dsl::*;
198     diesel::delete(
199       post_saved
200         .filter(post_id.eq(post_saved_form.post_id))
201         .filter(user_id.eq(post_saved_form.user_id)),
202     )
203     .execute(conn)
204   }
205 }
206
207 impl Readable<PostReadForm> for PostRead {
208   fn mark_as_read(conn: &PgConnection, post_read_form: &PostReadForm) -> Result<Self, Error> {
209     use lemmy_db_schema::schema::post_read::dsl::*;
210     insert_into(post_read)
211       .values(post_read_form)
212       .get_result::<Self>(conn)
213   }
214
215   fn mark_as_unread(conn: &PgConnection, post_read_form: &PostReadForm) -> Result<usize, Error> {
216     use lemmy_db_schema::schema::post_read::dsl::*;
217     diesel::delete(
218       post_read
219         .filter(post_id.eq(post_read_form.post_id))
220         .filter(user_id.eq(post_read_form.user_id)),
221     )
222     .execute(conn)
223   }
224 }
225
226 #[cfg(test)]
227 mod tests {
228   use crate::{establish_unpooled_connection, source::post::*, ListingType, SortType};
229   use lemmy_db_schema::source::{
230     community::{Community, CommunityForm},
231     user::*,
232   };
233
234   #[test]
235   fn test_crud() {
236     let conn = establish_unpooled_connection();
237
238     let new_user = UserForm {
239       name: "jim".into(),
240       preferred_username: None,
241       password_encrypted: "nope".into(),
242       email: None,
243       matrix_user_id: None,
244       avatar: None,
245       banner: None,
246       admin: false,
247       banned: Some(false),
248       published: None,
249       updated: None,
250       show_nsfw: false,
251       theme: "browser".into(),
252       default_sort_type: SortType::Hot as i16,
253       default_listing_type: ListingType::Subscribed as i16,
254       lang: "browser".into(),
255       show_avatars: true,
256       send_notifications_to_email: false,
257       actor_id: None,
258       bio: None,
259       local: true,
260       private_key: None,
261       public_key: None,
262       last_refreshed_at: None,
263     };
264
265     let inserted_user = User_::create(&conn, &new_user).unwrap();
266
267     let new_community = CommunityForm {
268       name: "test community_3".to_string(),
269       title: "nada".to_owned(),
270       description: None,
271       category_id: 1,
272       creator_id: inserted_user.id,
273       removed: None,
274       deleted: None,
275       updated: None,
276       nsfw: false,
277       actor_id: None,
278       local: true,
279       private_key: None,
280       public_key: None,
281       last_refreshed_at: None,
282       published: None,
283       icon: None,
284       banner: None,
285     };
286
287     let inserted_community = Community::create(&conn, &new_community).unwrap();
288
289     let new_post = PostForm {
290       name: "A test post".into(),
291       url: None,
292       body: None,
293       creator_id: inserted_user.id,
294       community_id: inserted_community.id,
295       removed: None,
296       deleted: None,
297       locked: None,
298       stickied: None,
299       nsfw: false,
300       updated: None,
301       embed_title: None,
302       embed_description: None,
303       embed_html: None,
304       thumbnail_url: None,
305       ap_id: None,
306       local: true,
307       published: None,
308     };
309
310     let inserted_post = Post::create(&conn, &new_post).unwrap();
311
312     let expected_post = Post {
313       id: inserted_post.id,
314       name: "A test post".into(),
315       url: None,
316       body: None,
317       creator_id: inserted_user.id,
318       community_id: inserted_community.id,
319       published: inserted_post.published,
320       removed: false,
321       locked: false,
322       stickied: false,
323       nsfw: false,
324       deleted: false,
325       updated: None,
326       embed_title: None,
327       embed_description: None,
328       embed_html: None,
329       thumbnail_url: None,
330       ap_id: inserted_post.ap_id.to_owned(),
331       local: true,
332     };
333
334     // Post Like
335     let post_like_form = PostLikeForm {
336       post_id: inserted_post.id,
337       user_id: inserted_user.id,
338       score: 1,
339     };
340
341     let inserted_post_like = PostLike::like(&conn, &post_like_form).unwrap();
342
343     let expected_post_like = PostLike {
344       id: inserted_post_like.id,
345       post_id: inserted_post.id,
346       user_id: inserted_user.id,
347       published: inserted_post_like.published,
348       score: 1,
349     };
350
351     // Post Save
352     let post_saved_form = PostSavedForm {
353       post_id: inserted_post.id,
354       user_id: inserted_user.id,
355     };
356
357     let inserted_post_saved = PostSaved::save(&conn, &post_saved_form).unwrap();
358
359     let expected_post_saved = PostSaved {
360       id: inserted_post_saved.id,
361       post_id: inserted_post.id,
362       user_id: inserted_user.id,
363       published: inserted_post_saved.published,
364     };
365
366     // Post Read
367     let post_read_form = PostReadForm {
368       post_id: inserted_post.id,
369       user_id: inserted_user.id,
370     };
371
372     let inserted_post_read = PostRead::mark_as_read(&conn, &post_read_form).unwrap();
373
374     let expected_post_read = PostRead {
375       id: inserted_post_read.id,
376       post_id: inserted_post.id,
377       user_id: inserted_user.id,
378       published: inserted_post_read.published,
379     };
380
381     let read_post = Post::read(&conn, inserted_post.id).unwrap();
382     let updated_post = Post::update(&conn, inserted_post.id, &new_post).unwrap();
383     let like_removed = PostLike::remove(&conn, inserted_user.id, inserted_post.id).unwrap();
384     let saved_removed = PostSaved::unsave(&conn, &post_saved_form).unwrap();
385     let read_removed = PostRead::mark_as_unread(&conn, &post_read_form).unwrap();
386     let num_deleted = Post::delete(&conn, inserted_post.id).unwrap();
387     Community::delete(&conn, inserted_community.id).unwrap();
388     User_::delete(&conn, inserted_user.id).unwrap();
389
390     assert_eq!(expected_post, read_post);
391     assert_eq!(expected_post, inserted_post);
392     assert_eq!(expected_post, updated_post);
393     assert_eq!(expected_post_like, inserted_post_like);
394     assert_eq!(expected_post_saved, inserted_post_saved);
395     assert_eq!(expected_post_read, inserted_post_read);
396     assert_eq!(1, like_removed);
397     assert_eq!(1, saved_removed);
398     assert_eq!(1, read_removed);
399     assert_eq!(1, num_deleted);
400   }
401 }