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 {
48 impl Perform<CommentResponse> for Oper<CreateComment> {
49 fn perform(&self) -> Result<CommentResponse, Error> {
50 let data: &CreateComment = &self.data;
51 let conn = establish_connection();
53 let claims = match Claims::decode(&data.auth) {
54 Ok(claims) => claims.claims,
56 return Err(APIError::err(&self.op, "Not logged in."))?
60 let user_id = claims.id;
62 // Check for a community ban
63 let post = Post::read(&conn, data.post_id)?;
64 if CommunityUserBanView::get(&conn, user_id, post.community_id).is_ok() {
65 return Err(APIError::err(&self.op, "You have been banned from this community"))?
68 // Check for a site ban
69 if UserView::read(&conn, user_id)?.banned {
70 return Err(APIError::err(&self.op, "You have been banned from the site"))?
73 let content_slurs_removed = remove_slurs(&data.content.to_owned());
75 let comment_form = CommentForm {
76 content: content_slurs_removed,
77 parent_id: data.parent_id.to_owned(),
78 post_id: data.post_id,
86 let inserted_comment = match Comment::create(&conn, &comment_form) {
87 Ok(comment) => comment,
89 return Err(APIError::err(&self.op, "Couldn't create Comment"))?
93 // You like your own comment by default
94 let like_form = CommentLikeForm {
95 comment_id: inserted_comment.id,
96 post_id: data.post_id,
101 let _inserted_like = match CommentLike::like(&conn, &like_form) {
104 return Err(APIError::err(&self.op, "Couldn't like comment."))?
108 let comment_view = CommentView::read(&conn, inserted_comment.id, Some(user_id))?;
112 op: self.op.to_string(),
113 comment: comment_view
119 impl Perform<CommentResponse> for Oper<EditComment> {
120 fn perform(&self) -> Result<CommentResponse, Error> {
121 let data: &EditComment = &self.data;
122 let conn = establish_connection();
124 let claims = match Claims::decode(&data.auth) {
125 Ok(claims) => claims.claims,
127 return Err(APIError::err(&self.op, "Not logged in."))?
131 let user_id = claims.id;
133 let orig_comment = CommentView::read(&conn, data.edit_id, None)?;
135 // You are allowed to mark the comment as read even if you're banned.
136 if data.read.is_none() {
138 // Verify its the creator or a mod, or an admin
139 let mut editors: Vec<i32> = vec![data.creator_id];
141 &mut CommunityModeratorView::for_community(&conn, orig_comment.community_id)
148 &mut UserView::admins(&conn)
155 if !editors.contains(&user_id) {
156 return Err(APIError::err(&self.op, "Not allowed to edit comment."))?
159 // Check for a community ban
160 if CommunityUserBanView::get(&conn, user_id, orig_comment.community_id).is_ok() {
161 return Err(APIError::err(&self.op, "You have been banned from this community"))?
164 // Check for a site ban
165 if UserView::read(&conn, user_id)?.banned {
166 return Err(APIError::err(&self.op, "You have been banned from the site"))?
171 let content_slurs_removed = remove_slurs(&data.content.to_owned());
173 let comment_form = CommentForm {
174 content: content_slurs_removed,
175 parent_id: data.parent_id,
176 post_id: data.post_id,
177 creator_id: data.creator_id,
178 removed: data.removed.to_owned(),
179 deleted: data.deleted.to_owned(),
180 read: data.read.to_owned(),
181 updated: if data.read.is_some() { orig_comment.updated } else {Some(naive_now())}
184 let _updated_comment = match Comment::update(&conn, data.edit_id, &comment_form) {
185 Ok(comment) => comment,
187 return Err(APIError::err(&self.op, "Couldn't update Comment"))?
192 if let Some(removed) = data.removed.to_owned() {
193 let form = ModRemoveCommentForm {
194 mod_user_id: user_id,
195 comment_id: data.edit_id,
196 removed: Some(removed),
197 reason: data.reason.to_owned(),
199 ModRemoveComment::create(&conn, &form)?;
203 let comment_view = CommentView::read(&conn, data.edit_id, Some(user_id))?;
207 op: self.op.to_string(),
208 comment: comment_view
215 impl Perform<CommentResponse> for Oper<SaveComment> {
216 fn perform(&self) -> Result<CommentResponse, Error> {
217 let data: &SaveComment = &self.data;
218 let conn = establish_connection();
220 let claims = match Claims::decode(&data.auth) {
221 Ok(claims) => claims.claims,
223 return Err(APIError::err(&self.op, "Not logged in."))?
227 let user_id = claims.id;
229 let comment_saved_form = CommentSavedForm {
230 comment_id: data.comment_id,
235 match CommentSaved::save(&conn, &comment_saved_form) {
236 Ok(comment) => comment,
238 return Err(APIError::err(&self.op, "Couldnt do comment save"))?
242 match CommentSaved::unsave(&conn, &comment_saved_form) {
243 Ok(comment) => comment,
245 return Err(APIError::err(&self.op, "Couldnt do comment save"))?
250 let comment_view = CommentView::read(&conn, data.comment_id, Some(user_id))?;
254 op: self.op.to_string(),
255 comment: comment_view
261 impl Perform<CommentResponse> for Oper<CreateCommentLike> {
262 fn perform(&self) -> Result<CommentResponse, Error> {
263 let data: &CreateCommentLike = &self.data;
264 let conn = establish_connection();
266 let claims = match Claims::decode(&data.auth) {
267 Ok(claims) => claims.claims,
269 return Err(APIError::err(&self.op, "Not logged in."))?
273 let user_id = claims.id;
275 // Check for a community ban
276 let post = Post::read(&conn, data.post_id)?;
277 if CommunityUserBanView::get(&conn, user_id, post.community_id).is_ok() {
278 return Err(APIError::err(&self.op, "You have been banned from this community"))?
281 // Check for a site ban
282 if UserView::read(&conn, user_id)?.banned {
283 return Err(APIError::err(&self.op, "You have been banned from the site"))?
286 let like_form = CommentLikeForm {
287 comment_id: data.comment_id,
288 post_id: data.post_id,
293 // Remove any likes first
294 CommentLike::remove(&conn, &like_form)?;
296 // Only add the like if the score isnt 0
297 let do_add = &like_form.score != &0 && (&like_form.score == &1 || &like_form.score == &-1);
299 let _inserted_like = match CommentLike::like(&conn, &like_form) {
302 return Err(APIError::err(&self.op, "Couldn't like comment."))?
307 // Have to refetch the comment to get the current state
308 let liked_comment = CommentView::read(&conn, data.comment_id, Some(user_id))?;
312 op: self.op.to_string(),
313 comment: liked_comment