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