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