4 #[derive(Serialize, Deserialize)]
5 pub struct CreatePost {
14 #[derive(Serialize, Deserialize, Clone)]
15 pub struct PostResponse {
21 #[derive(Serialize, Deserialize)]
27 #[derive(Serialize, Deserialize)]
28 pub struct GetPostResponse {
31 comments: Vec<CommentView>,
32 community: CommunityView,
33 moderators: Vec<CommunityModeratorView>,
34 admins: Vec<UserView>,
37 #[derive(Serialize, Deserialize)]
43 community_id: Option<i32>,
47 #[derive(Serialize, Deserialize)]
48 pub struct GetPostsResponse {
53 #[derive(Serialize, Deserialize)]
54 pub struct CreatePostLike {
60 #[derive(Serialize, Deserialize)]
61 pub struct CreatePostLikeResponse {
67 #[derive(Serialize, Deserialize)]
75 removed: Option<bool>,
76 deleted: Option<bool>,
79 reason: Option<String>,
83 #[derive(Serialize, Deserialize)]
90 impl Perform<PostResponse> for Oper<CreatePost> {
91 fn perform(&self) -> Result<PostResponse, Error> {
92 let data: &CreatePost = &self.data;
93 let conn = establish_connection();
96 let claims = match Claims::decode(&data.auth) {
97 Ok(claims) => claims.claims,
99 return Err(APIError::err(&self.op, "not_logged_in"))?
103 if has_slurs(&data.name) ||
104 (data.body.is_some() && has_slurs(&data.body.to_owned().unwrap())) {
105 return Err(APIError::err(&self.op, "no_slurs"))?
108 let user_id = claims.id;
110 // Check for a community ban
111 if CommunityUserBanView::get(&conn, user_id, data.community_id).is_ok() {
112 return Err(APIError::err(&self.op, "community_ban"))?
115 // Check for a site ban
116 if UserView::read(&conn, user_id)?.banned {
117 return Err(APIError::err(&self.op, "site_ban"))?
120 let post_form = PostForm {
121 name: data.name.to_owned(),
122 url: data.url.to_owned(),
123 body: data.body.to_owned(),
124 community_id: data.community_id,
133 let inserted_post = match Post::create(&conn, &post_form) {
136 return Err(APIError::err(&self.op, "couldnt_create_post"))?
140 // They like their own post by default
141 let like_form = PostLikeForm {
142 post_id: inserted_post.id,
147 // Only add the like if the score isnt 0
148 let _inserted_like = match PostLike::like(&conn, &like_form) {
151 return Err(APIError::err(&self.op, "couldnt_like_post"))?
156 let post_view = match PostView::read(&conn, inserted_post.id, Some(user_id)) {
159 return Err(APIError::err(&self.op, "couldnt_find_post"))?
165 op: self.op.to_string(),
172 impl Perform<GetPostResponse> for Oper<GetPost> {
173 fn perform(&self) -> Result<GetPostResponse, Error> {
174 let data: &GetPost = &self.data;
175 let conn = establish_connection();
177 let user_id: Option<i32> = match &data.auth {
179 match Claims::decode(&auth) {
181 let user_id = claims.claims.id;
190 let post_view = match PostView::read(&conn, data.id, user_id) {
193 return Err(APIError::err(&self.op, "couldnt_find_post"))?
197 let comments = CommentView::list(&conn, &SortType::New, Some(data.id), None, None, user_id, false, None, Some(9999))?;
199 let community = CommunityView::read(&conn, post_view.community_id, user_id)?;
201 let moderators = CommunityModeratorView::for_community(&conn, post_view.community_id)?;
203 let site_creator_id = Site::read(&conn, 1)?.creator_id;
204 let mut admins = UserView::admins(&conn)?;
205 let creator_index = admins.iter().position(|r| r.id == site_creator_id).unwrap();
206 let creator_user = admins.remove(creator_index);
207 admins.insert(0, creator_user);
212 op: self.op.to_string(),
215 community: community,
216 moderators: moderators,
224 impl Perform<GetPostsResponse> for Oper<GetPosts> {
225 fn perform(&self) -> Result<GetPostsResponse, Error> {
226 let data: &GetPosts = &self.data;
227 let conn = establish_connection();
229 let user_claims: Option<Claims> = match &data.auth {
231 match Claims::decode(&auth) {
241 let user_id = match &user_claims {
242 Some(claims) => Some(claims.id),
246 let show_nsfw = match &user_claims {
247 Some(claims) => claims.show_nsfw,
251 let type_ = PostListingType::from_str(&data.type_)?;
252 let sort = SortType::from_str(&data.sort)?;
254 let posts = match PostView::list(
270 return Err(APIError::err(&self.op, "couldnt_get_posts"))?
276 op: self.op.to_string(),
283 impl Perform<CreatePostLikeResponse> for Oper<CreatePostLike> {
284 fn perform(&self) -> Result<CreatePostLikeResponse, Error> {
285 let data: &CreatePostLike = &self.data;
286 let conn = establish_connection();
288 let claims = match Claims::decode(&data.auth) {
289 Ok(claims) => claims.claims,
291 return Err(APIError::err(&self.op, "not_logged_in"))?
295 let user_id = claims.id;
297 // Check for a community ban
298 let post = Post::read(&conn, data.post_id)?;
299 if CommunityUserBanView::get(&conn, user_id, post.community_id).is_ok() {
300 return Err(APIError::err(&self.op, "community_ban"))?
303 // Check for a site ban
304 if UserView::read(&conn, user_id)?.banned {
305 return Err(APIError::err(&self.op, "site_ban"))?
308 let like_form = PostLikeForm {
309 post_id: data.post_id,
314 // Remove any likes first
315 PostLike::remove(&conn, &like_form)?;
317 // Only add the like if the score isnt 0
318 let do_add = &like_form.score != &0 && (&like_form.score == &1 || &like_form.score == &-1);
320 let _inserted_like = match PostLike::like(&conn, &like_form) {
323 return Err(APIError::err(&self.op, "couldnt_like_post"))?
328 let post_view = match PostView::read(&conn, data.post_id, Some(user_id)) {
331 return Err(APIError::err(&self.op, "couldnt_find_post"))?
335 // just output the score
337 CreatePostLikeResponse {
338 op: self.op.to_string(),
345 impl Perform<PostResponse> for Oper<EditPost> {
346 fn perform(&self) -> Result<PostResponse, Error> {
347 let data: &EditPost = &self.data;
348 if has_slurs(&data.name) ||
349 (data.body.is_some() && has_slurs(&data.body.to_owned().unwrap())) {
350 return Err(APIError::err(&self.op, "no_slurs"))?
353 let conn = establish_connection();
355 let claims = match Claims::decode(&data.auth) {
356 Ok(claims) => claims.claims,
358 return Err(APIError::err(&self.op, "not_logged_in"))?
362 let user_id = claims.id;
364 // Verify its the creator or a mod or admin
365 let mut editors: Vec<i32> = vec![data.creator_id];
367 &mut CommunityModeratorView::for_community(&conn, data.community_id)
374 &mut UserView::admins(&conn)
380 if !editors.contains(&user_id) {
381 return Err(APIError::err(&self.op, "no_post_edit_allowed"))?
384 // Check for a community ban
385 if CommunityUserBanView::get(&conn, user_id, data.community_id).is_ok() {
386 return Err(APIError::err(&self.op, "community_ban"))?
389 // Check for a site ban
390 if UserView::read(&conn, user_id)?.banned {
391 return Err(APIError::err(&self.op, "site_ban"))?
394 let post_form = PostForm {
395 name: data.name.to_owned(),
396 url: data.url.to_owned(),
397 body: data.body.to_owned(),
398 creator_id: data.creator_id.to_owned(),
399 community_id: data.community_id,
400 removed: data.removed.to_owned(),
401 deleted: data.deleted.to_owned(),
403 locked: data.locked.to_owned(),
404 updated: Some(naive_now())
407 let _updated_post = match Post::update(&conn, data.edit_id, &post_form) {
410 return Err(APIError::err(&self.op, "couldnt_update_post"))?
415 if let Some(removed) = data.removed.to_owned() {
416 let form = ModRemovePostForm {
417 mod_user_id: user_id,
418 post_id: data.edit_id,
419 removed: Some(removed),
420 reason: data.reason.to_owned(),
422 ModRemovePost::create(&conn, &form)?;
425 if let Some(locked) = data.locked.to_owned() {
426 let form = ModLockPostForm {
427 mod_user_id: user_id,
428 post_id: data.edit_id,
429 locked: Some(locked),
431 ModLockPost::create(&conn, &form)?;
434 let post_view = PostView::read(&conn, data.edit_id, Some(user_id))?;
438 op: self.op.to_string(),
445 impl Perform<PostResponse> for Oper<SavePost> {
446 fn perform(&self) -> Result<PostResponse, Error> {
447 let data: &SavePost = &self.data;
448 let conn = establish_connection();
450 let claims = match Claims::decode(&data.auth) {
451 Ok(claims) => claims.claims,
453 return Err(APIError::err(&self.op, "not_logged_in"))?
457 let user_id = claims.id;
459 let post_saved_form = PostSavedForm {
460 post_id: data.post_id,
465 match PostSaved::save(&conn, &post_saved_form) {
468 return Err(APIError::err(&self.op, "couldnt_save_post"))?
472 match PostSaved::unsave(&conn, &post_saved_form) {
475 return Err(APIError::err(&self.op, "couldnt_save_post"))?
480 let post_view = PostView::read(&conn, data.post_id, Some(user_id))?;
484 op: self.op.to_string(),