3 #[derive(Serialize, Deserialize)]
4 pub struct CreateComment {
6 parent_id: Option<i32>,
12 #[derive(Serialize, Deserialize)]
13 pub struct EditComment {
15 parent_id: Option<i32>,
19 removed: Option<bool>,
20 deleted: Option<bool>,
21 reason: Option<String>,
26 #[derive(Serialize, Deserialize)]
27 pub struct SaveComment {
33 #[derive(Serialize, Deserialize, Clone)]
34 pub struct CommentResponse {
36 pub comment: CommentView,
39 #[derive(Serialize, Deserialize)]
40 pub struct CreateCommentLike {
47 impl Perform<CommentResponse> for Oper<CreateComment> {
48 fn perform(&self) -> Result<CommentResponse, Error> {
49 let data: &CreateComment = &self.data;
50 let conn = establish_connection();
52 let claims = match Claims::decode(&data.auth) {
53 Ok(claims) => claims.claims,
54 Err(_e) => return Err(APIError::err(&self.op, "not_logged_in"))?,
57 let user_id = claims.id;
59 // Check for a community ban
60 let post = Post::read(&conn, data.post_id)?;
61 if CommunityUserBanView::get(&conn, user_id, post.community_id).is_ok() {
62 return Err(APIError::err(&self.op, "community_ban"))?;
65 // Check for a site ban
66 if UserView::read(&conn, user_id)?.banned {
67 return Err(APIError::err(&self.op, "site_ban"))?;
70 let content_slurs_removed = remove_slurs(&data.content.to_owned());
72 let comment_form = CommentForm {
73 content: content_slurs_removed,
74 parent_id: data.parent_id.to_owned(),
75 post_id: data.post_id,
83 let inserted_comment = match Comment::create(&conn, &comment_form) {
84 Ok(comment) => comment,
85 Err(_e) => return Err(APIError::err(&self.op, "couldnt_create_comment"))?,
88 // You like your own comment by default
89 let like_form = CommentLikeForm {
90 comment_id: inserted_comment.id,
91 post_id: data.post_id,
96 let _inserted_like = match CommentLike::like(&conn, &like_form) {
98 Err(_e) => return Err(APIError::err(&self.op, "couldnt_like_comment"))?,
101 let comment_view = CommentView::read(&conn, inserted_comment.id, Some(user_id))?;
104 op: self.op.to_string(),
105 comment: comment_view,
110 impl Perform<CommentResponse> for Oper<EditComment> {
111 fn perform(&self) -> Result<CommentResponse, Error> {
112 let data: &EditComment = &self.data;
113 let conn = establish_connection();
115 let claims = match Claims::decode(&data.auth) {
116 Ok(claims) => claims.claims,
117 Err(_e) => return Err(APIError::err(&self.op, "not_logged_in"))?,
120 let user_id = claims.id;
122 let orig_comment = CommentView::read(&conn, data.edit_id, None)?;
124 // You are allowed to mark the comment as read even if you're banned.
125 if data.read.is_none() {
126 // Verify its the creator or a mod, or an admin
127 let mut editors: Vec<i32> = vec![data.creator_id];
129 &mut CommunityModeratorView::for_community(&conn, orig_comment.community_id)?
134 editors.append(&mut UserView::admins(&conn)?.into_iter().map(|a| a.id).collect());
136 if !editors.contains(&user_id) {
137 return Err(APIError::err(&self.op, "no_comment_edit_allowed"))?;
140 // Check for a community ban
141 if CommunityUserBanView::get(&conn, user_id, orig_comment.community_id).is_ok() {
142 return Err(APIError::err(&self.op, "community_ban"))?;
145 // Check for a site ban
146 if UserView::read(&conn, user_id)?.banned {
147 return Err(APIError::err(&self.op, "site_ban"))?;
151 let content_slurs_removed = remove_slurs(&data.content.to_owned());
153 let comment_form = CommentForm {
154 content: content_slurs_removed,
155 parent_id: data.parent_id,
156 post_id: data.post_id,
157 creator_id: data.creator_id,
158 removed: data.removed.to_owned(),
159 deleted: data.deleted.to_owned(),
160 read: data.read.to_owned(),
161 updated: if data.read.is_some() {
168 let _updated_comment = match Comment::update(&conn, data.edit_id, &comment_form) {
169 Ok(comment) => comment,
170 Err(_e) => return Err(APIError::err(&self.op, "couldnt_update_comment"))?,
174 if let Some(removed) = data.removed.to_owned() {
175 let form = ModRemoveCommentForm {
176 mod_user_id: user_id,
177 comment_id: data.edit_id,
178 removed: Some(removed),
179 reason: data.reason.to_owned(),
181 ModRemoveComment::create(&conn, &form)?;
184 let comment_view = CommentView::read(&conn, data.edit_id, Some(user_id))?;
187 op: self.op.to_string(),
188 comment: comment_view,
193 impl Perform<CommentResponse> for Oper<SaveComment> {
194 fn perform(&self) -> Result<CommentResponse, Error> {
195 let data: &SaveComment = &self.data;
196 let conn = establish_connection();
198 let claims = match Claims::decode(&data.auth) {
199 Ok(claims) => claims.claims,
200 Err(_e) => return Err(APIError::err(&self.op, "not_logged_in"))?,
203 let user_id = claims.id;
205 let comment_saved_form = CommentSavedForm {
206 comment_id: data.comment_id,
211 match CommentSaved::save(&conn, &comment_saved_form) {
212 Ok(comment) => comment,
213 Err(_e) => return Err(APIError::err(&self.op, "couldnt_save_comment"))?,
216 match CommentSaved::unsave(&conn, &comment_saved_form) {
217 Ok(comment) => comment,
218 Err(_e) => return Err(APIError::err(&self.op, "couldnt_save_comment"))?,
222 let comment_view = CommentView::read(&conn, data.comment_id, Some(user_id))?;
225 op: self.op.to_string(),
226 comment: comment_view,
231 impl Perform<CommentResponse> for Oper<CreateCommentLike> {
232 fn perform(&self) -> Result<CommentResponse, Error> {
233 let data: &CreateCommentLike = &self.data;
234 let conn = establish_connection();
236 let claims = match Claims::decode(&data.auth) {
237 Ok(claims) => claims.claims,
238 Err(_e) => return Err(APIError::err(&self.op, "not_logged_in"))?,
241 let user_id = claims.id;
243 // Check for a community ban
244 let post = Post::read(&conn, data.post_id)?;
245 if CommunityUserBanView::get(&conn, user_id, post.community_id).is_ok() {
246 return Err(APIError::err(&self.op, "community_ban"))?;
249 // Check for a site ban
250 if UserView::read(&conn, user_id)?.banned {
251 return Err(APIError::err(&self.op, "site_ban"))?;
254 let like_form = CommentLikeForm {
255 comment_id: data.comment_id,
256 post_id: data.post_id,
261 // Remove any likes first
262 CommentLike::remove(&conn, &like_form)?;
264 // Only add the like if the score isnt 0
265 let do_add = &like_form.score != &0 && (&like_form.score == &1 || &like_form.score == &-1);
267 let _inserted_like = match CommentLike::like(&conn, &like_form) {
269 Err(_e) => return Err(APIError::err(&self.op, "couldnt_like_comment"))?,
273 // Have to refetch the comment to get the current state
274 let liked_comment = CommentView::read(&conn, data.comment_id, Some(user_id))?;
277 op: self.op.to_string(),
278 comment: liked_comment,