]> Untitled Git - lemmy.git/commitdiff
working!
authorFelix <me@nutomic.com>
Thu, 16 Jan 2020 14:39:08 +0000 (15:39 +0100)
committerFelix <me@nutomic.com>
Sat, 18 Jan 2020 13:26:04 +0000 (14:26 +0100)
server/src/api/comment.rs
server/src/api/community.rs
server/src/api/mod.rs
server/src/api/post.rs
server/src/api/site.rs
server/src/api/user.rs
server/src/routes/api.rs
server/src/websocket/mod.rs
server/src/websocket/server.rs

index 61cc95063344c5af6618b95a3ae157cf6835bb21..d26c2dce22a20bf2cba4fa344dfcabf2ac0684f5 100644 (file)
@@ -35,7 +35,6 @@ pub struct SaveComment {
 
 #[derive(Serialize, Deserialize, Clone)]
 pub struct CommentResponse {
-  op: String,
   pub comment: CommentView,
 }
 
@@ -53,7 +52,7 @@ impl Perform<CommentResponse> for Oper<CreateComment> {
 
     let claims = match Claims::decode(&data.auth) {
       Ok(claims) => claims.claims,
-      Err(_e) => return Err(APIError::err(&self.op, "not_logged_in").into()),
+      Err(_e) => return Err(APIError::err("not_logged_in").into()),
     };
 
     let user_id = claims.id;
@@ -63,12 +62,12 @@ impl Perform<CommentResponse> for Oper<CreateComment> {
     // Check for a community ban
     let post = Post::read(&conn, data.post_id)?;
     if CommunityUserBanView::get(&conn, user_id, post.community_id).is_ok() {
-      return Err(APIError::err(&self.op, "community_ban").into());
+      return Err(APIError::err("community_ban").into());
     }
 
     // Check for a site ban
     if UserView::read(&conn, user_id)?.banned {
-      return Err(APIError::err(&self.op, "site_ban").into());
+      return Err(APIError::err("site_ban").into());
     }
 
     let content_slurs_removed = remove_slurs(&data.content.to_owned());
@@ -86,7 +85,7 @@ impl Perform<CommentResponse> for Oper<CreateComment> {
 
     let inserted_comment = match Comment::create(&conn, &comment_form) {
       Ok(comment) => comment,
-      Err(_e) => return Err(APIError::err(&self.op, "couldnt_create_comment").into()),
+      Err(_e) => return Err(APIError::err("couldnt_create_comment").into()),
     };
 
     // Scan the comment for user mentions, add those rows
@@ -193,13 +192,12 @@ impl Perform<CommentResponse> for Oper<CreateComment> {
 
     let _inserted_like = match CommentLike::like(&conn, &like_form) {
       Ok(like) => like,
-      Err(_e) => return Err(APIError::err(&self.op, "couldnt_like_comment").into()),
+      Err(_e) => return Err(APIError::err("couldnt_like_comment").into()),
     };
 
     let comment_view = CommentView::read(&conn, inserted_comment.id, Some(user_id))?;
 
     Ok(CommentResponse {
-      op: self.op.to_string(),
       comment: comment_view,
     })
   }
@@ -211,7 +209,7 @@ impl Perform<CommentResponse> for Oper<EditComment> {
 
     let claims = match Claims::decode(&data.auth) {
       Ok(claims) => claims.claims,
-      Err(_e) => return Err(APIError::err(&self.op, "not_logged_in").into()),
+      Err(_e) => return Err(APIError::err("not_logged_in").into()),
     };
 
     let user_id = claims.id;
@@ -231,17 +229,17 @@ impl Perform<CommentResponse> for Oper<EditComment> {
       editors.append(&mut UserView::admins(&conn)?.into_iter().map(|a| a.id).collect());
 
       if !editors.contains(&user_id) {
-        return Err(APIError::err(&self.op, "no_comment_edit_allowed").into());
+        return Err(APIError::err("no_comment_edit_allowed").into());
       }
 
       // Check for a community ban
       if CommunityUserBanView::get(&conn, user_id, orig_comment.community_id).is_ok() {
-        return Err(APIError::err(&self.op, "community_ban").into());
+        return Err(APIError::err("community_ban").into());
       }
 
       // Check for a site ban
       if UserView::read(&conn, user_id)?.banned {
-        return Err(APIError::err(&self.op, "site_ban").into());
+        return Err(APIError::err("site_ban").into());
       }
     }
 
@@ -264,7 +262,7 @@ impl Perform<CommentResponse> for Oper<EditComment> {
 
     let _updated_comment = match Comment::update(&conn, data.edit_id, &comment_form) {
       Ok(comment) => comment,
-      Err(_e) => return Err(APIError::err(&self.op, "couldnt_update_comment").into()),
+      Err(_e) => return Err(APIError::err("couldnt_update_comment").into()),
     };
 
     // Scan the comment for user mentions, add those rows
@@ -310,7 +308,6 @@ impl Perform<CommentResponse> for Oper<EditComment> {
     let comment_view = CommentView::read(&conn, data.edit_id, Some(user_id))?;
 
     Ok(CommentResponse {
-      op: self.op.to_string(),
       comment: comment_view,
     })
   }
@@ -322,7 +319,7 @@ impl Perform<CommentResponse> for Oper<SaveComment> {
 
     let claims = match Claims::decode(&data.auth) {
       Ok(claims) => claims.claims,
-      Err(_e) => return Err(APIError::err(&self.op, "not_logged_in").into()),
+      Err(_e) => return Err(APIError::err("not_logged_in").into()),
     };
 
     let user_id = claims.id;
@@ -335,19 +332,18 @@ impl Perform<CommentResponse> for Oper<SaveComment> {
     if data.save {
       match CommentSaved::save(&conn, &comment_saved_form) {
         Ok(comment) => comment,
-        Err(_e) => return Err(APIError::err(&self.op, "couldnt_save_comment").into()),
+        Err(_e) => return Err(APIError::err("couldnt_save_comment").into()),
       };
     } else {
       match CommentSaved::unsave(&conn, &comment_saved_form) {
         Ok(comment) => comment,
-        Err(_e) => return Err(APIError::err(&self.op, "couldnt_save_comment").into()),
+        Err(_e) => return Err(APIError::err("couldnt_save_comment").into()),
       };
     }
 
     let comment_view = CommentView::read(&conn, data.comment_id, Some(user_id))?;
 
     Ok(CommentResponse {
-      op: self.op.to_string(),
       comment: comment_view,
     })
   }
@@ -359,7 +355,7 @@ impl Perform<CommentResponse> for Oper<CreateCommentLike> {
 
     let claims = match Claims::decode(&data.auth) {
       Ok(claims) => claims.claims,
-      Err(_e) => return Err(APIError::err(&self.op, "not_logged_in").into()),
+      Err(_e) => return Err(APIError::err("not_logged_in").into()),
     };
 
     let user_id = claims.id;
@@ -368,19 +364,19 @@ impl Perform<CommentResponse> for Oper<CreateCommentLike> {
     if data.score == -1 {
       let site = SiteView::read(&conn)?;
       if !site.enable_downvotes {
-        return Err(APIError::err(&self.op, "downvotes_disabled").into());
+        return Err(APIError::err("downvotes_disabled").into());
       }
     }
 
     // Check for a community ban
     let post = Post::read(&conn, data.post_id)?;
     if CommunityUserBanView::get(&conn, user_id, post.community_id).is_ok() {
-      return Err(APIError::err(&self.op, "community_ban").into());
+      return Err(APIError::err("community_ban").into());
     }
 
     // Check for a site ban
     if UserView::read(&conn, user_id)?.banned {
-      return Err(APIError::err(&self.op, "site_ban").into());
+      return Err(APIError::err("site_ban").into());
     }
 
     let like_form = CommentLikeForm {
@@ -398,7 +394,7 @@ impl Perform<CommentResponse> for Oper<CreateCommentLike> {
     if do_add {
       let _inserted_like = match CommentLike::like(&conn, &like_form) {
         Ok(like) => like,
-        Err(_e) => return Err(APIError::err(&self.op, "couldnt_like_comment").into()),
+        Err(_e) => return Err(APIError::err("couldnt_like_comment").into()),
       };
     }
 
@@ -406,7 +402,6 @@ impl Perform<CommentResponse> for Oper<CreateCommentLike> {
     let liked_comment = CommentView::read(&conn, data.comment_id, Some(user_id))?;
 
     Ok(CommentResponse {
-      op: self.op.to_string(),
       comment: liked_comment,
     })
   }
index 0bf846c3d9dd4488a1bf62811657b339114fdce9..c765aa9dd84587a2e184fdb6b7b4bee510ab52d7 100644 (file)
@@ -11,7 +11,6 @@ pub struct GetCommunity {
 
 #[derive(Serialize, Deserialize)]
 pub struct GetCommunityResponse {
-  op: String,
   community: CommunityView,
   moderators: Vec<CommunityModeratorView>,
   admins: Vec<UserView>,
@@ -29,7 +28,6 @@ pub struct CreateCommunity {
 
 #[derive(Serialize, Deserialize, Clone)]
 pub struct CommunityResponse {
-  op: String,
   pub community: CommunityView,
 }
 
@@ -43,7 +41,6 @@ pub struct ListCommunities {
 
 #[derive(Serialize, Deserialize)]
 pub struct ListCommunitiesResponse {
-  op: String,
   communities: Vec<CommunityView>,
 }
 
@@ -59,7 +56,6 @@ pub struct BanFromCommunity {
 
 #[derive(Serialize, Deserialize)]
 pub struct BanFromCommunityResponse {
-  op: String,
   user: UserView,
   banned: bool,
 }
@@ -74,7 +70,6 @@ pub struct AddModToCommunity {
 
 #[derive(Serialize, Deserialize)]
 pub struct AddModToCommunityResponse {
-  op: String,
   moderators: Vec<CommunityModeratorView>,
 }
 
@@ -107,7 +102,6 @@ pub struct GetFollowedCommunities {
 
 #[derive(Serialize, Deserialize)]
 pub struct GetFollowedCommunitiesResponse {
-  op: String,
   communities: Vec<CommunityFollowerView>,
 }
 
@@ -141,19 +135,19 @@ impl Perform<GetCommunityResponse> for Oper<GetCommunity> {
           data.name.to_owned().unwrap_or_else(|| "main".to_string()),
         ) {
           Ok(community) => community.id,
-          Err(_e) => return Err(APIError::err(&self.op, "couldnt_find_community").into()),
+          Err(_e) => return Err(APIError::err("couldnt_find_community").into()),
         }
       }
     };
 
     let community_view = match CommunityView::read(&conn, community_id, user_id) {
       Ok(community) => community,
-      Err(_e) => return Err(APIError::err(&self.op, "couldnt_find_community").into()),
+      Err(_e) => return Err(APIError::err("couldnt_find_community").into()),
     };
 
     let moderators = match CommunityModeratorView::for_community(&conn, community_id) {
       Ok(moderators) => moderators,
-      Err(_e) => return Err(APIError::err(&self.op, "couldnt_find_community").into()),
+      Err(_e) => return Err(APIError::err("couldnt_find_community").into()),
     };
 
     let site_creator_id = Site::read(&conn, 1)?.creator_id;
@@ -164,7 +158,6 @@ impl Perform<GetCommunityResponse> for Oper<GetCommunity> {
 
     // Return the jwt
     Ok(GetCommunityResponse {
-      op: self.op.to_string(),
       community: community_view,
       moderators,
       admins,
@@ -178,21 +171,21 @@ impl Perform<CommunityResponse> for Oper<CreateCommunity> {
 
     let claims = match Claims::decode(&data.auth) {
       Ok(claims) => claims.claims,
-      Err(_e) => return Err(APIError::err(&self.op, "not_logged_in").into()),
+      Err(_e) => return Err(APIError::err("not_logged_in").into()),
     };
 
     if has_slurs(&data.name)
       || has_slurs(&data.title)
       || (data.description.is_some() && has_slurs(&data.description.to_owned().unwrap()))
     {
-      return Err(APIError::err(&self.op, "no_slurs").into());
+      return Err(APIError::err("no_slurs").into());
     }
 
     let user_id = claims.id;
 
     // Check for a site ban
     if UserView::read(&conn, user_id)?.banned {
-      return Err(APIError::err(&self.op, "site_ban").into());
+      return Err(APIError::err("site_ban").into());
     }
 
     // When you create a community, make sure the user becomes a moderator and a follower
@@ -210,7 +203,7 @@ impl Perform<CommunityResponse> for Oper<CreateCommunity> {
 
     let inserted_community = match Community::create(&conn, &community_form) {
       Ok(community) => community,
-      Err(_e) => return Err(APIError::err(&self.op, "community_already_exists").into()),
+      Err(_e) => return Err(APIError::err("community_already_exists").into()),
     };
 
     let community_moderator_form = CommunityModeratorForm {
@@ -221,9 +214,7 @@ impl Perform<CommunityResponse> for Oper<CreateCommunity> {
     let _inserted_community_moderator =
       match CommunityModerator::join(&conn, &community_moderator_form) {
         Ok(user) => user,
-        Err(_e) => {
-          return Err(APIError::err(&self.op, "community_moderator_already_exists").into())
-        }
+        Err(_e) => return Err(APIError::err("community_moderator_already_exists").into()),
       };
 
     let community_follower_form = CommunityFollowerForm {
@@ -234,13 +225,12 @@ impl Perform<CommunityResponse> for Oper<CreateCommunity> {
     let _inserted_community_follower =
       match CommunityFollower::follow(&conn, &community_follower_form) {
         Ok(user) => user,
-        Err(_e) => return Err(APIError::err(&self.op, "community_follower_already_exists").into()),
+        Err(_e) => return Err(APIError::err("community_follower_already_exists").into()),
       };
 
     let community_view = CommunityView::read(&conn, inserted_community.id, Some(user_id))?;
 
     Ok(CommunityResponse {
-      op: self.op.to_string(),
       community: community_view,
     })
   }
@@ -251,19 +241,19 @@ impl Perform<CommunityResponse> for Oper<EditCommunity> {
     let data: &EditCommunity = &self.data;
 
     if has_slurs(&data.name) || has_slurs(&data.title) {
-      return Err(APIError::err(&self.op, "no_slurs").into());
+      return Err(APIError::err("no_slurs").into());
     }
 
     let claims = match Claims::decode(&data.auth) {
       Ok(claims) => claims.claims,
-      Err(_e) => return Err(APIError::err(&self.op, "not_logged_in").into()),
+      Err(_e) => return Err(APIError::err("not_logged_in").into()),
     };
 
     let user_id = claims.id;
 
     // Check for a site ban
     if UserView::read(&conn, user_id)?.banned {
-      return Err(APIError::err(&self.op, "site_ban").into());
+      return Err(APIError::err("site_ban").into());
     }
 
     // Verify its a mod
@@ -276,7 +266,7 @@ impl Perform<CommunityResponse> for Oper<EditCommunity> {
     );
     editors.append(&mut UserView::admins(&conn)?.into_iter().map(|a| a.id).collect());
     if !editors.contains(&user_id) {
-      return Err(APIError::err(&self.op, "no_community_edit_allowed").into());
+      return Err(APIError::err("no_community_edit_allowed").into());
     }
 
     let community_form = CommunityForm {
@@ -293,7 +283,7 @@ impl Perform<CommunityResponse> for Oper<EditCommunity> {
 
     let _updated_community = match Community::update(&conn, data.edit_id, &community_form) {
       Ok(community) => community,
-      Err(_e) => return Err(APIError::err(&self.op, "couldnt_update_community").into()),
+      Err(_e) => return Err(APIError::err("couldnt_update_community").into()),
     };
 
     // Mod tables
@@ -315,7 +305,6 @@ impl Perform<CommunityResponse> for Oper<EditCommunity> {
     let community_view = CommunityView::read(&conn, data.edit_id, Some(user_id))?;
 
     Ok(CommunityResponse {
-      op: self.op.to_string(),
       community: community_view,
     })
   }
@@ -354,10 +343,7 @@ impl Perform<ListCommunitiesResponse> for Oper<ListCommunities> {
       .list()?;
 
     // Return the jwt
-    Ok(ListCommunitiesResponse {
-      op: self.op.to_string(),
-      communities,
-    })
+    Ok(ListCommunitiesResponse { communities })
   }
 }
 
@@ -367,7 +353,7 @@ impl Perform<CommunityResponse> for Oper<FollowCommunity> {
 
     let claims = match Claims::decode(&data.auth) {
       Ok(claims) => claims.claims,
-      Err(_e) => return Err(APIError::err(&self.op, "not_logged_in").into()),
+      Err(_e) => return Err(APIError::err("not_logged_in").into()),
     };
 
     let user_id = claims.id;
@@ -380,19 +366,18 @@ impl Perform<CommunityResponse> for Oper<FollowCommunity> {
     if data.follow {
       match CommunityFollower::follow(&conn, &community_follower_form) {
         Ok(user) => user,
-        Err(_e) => return Err(APIError::err(&self.op, "community_follower_already_exists").into()),
+        Err(_e) => return Err(APIError::err("community_follower_already_exists").into()),
       };
     } else {
       match CommunityFollower::ignore(&conn, &community_follower_form) {
         Ok(user) => user,
-        Err(_e) => return Err(APIError::err(&self.op, "community_follower_already_exists").into()),
+        Err(_e) => return Err(APIError::err("community_follower_already_exists").into()),
       };
     }
 
     let community_view = CommunityView::read(&conn, data.community_id, Some(user_id))?;
 
     Ok(CommunityResponse {
-      op: self.op.to_string(),
       community: community_view,
     })
   }
@@ -404,7 +389,7 @@ impl Perform<GetFollowedCommunitiesResponse> for Oper<GetFollowedCommunities> {
 
     let claims = match Claims::decode(&data.auth) {
       Ok(claims) => claims.claims,
-      Err(_e) => return Err(APIError::err(&self.op, "not_logged_in").into()),
+      Err(_e) => return Err(APIError::err("not_logged_in").into()),
     };
 
     let user_id = claims.id;
@@ -412,14 +397,11 @@ impl Perform<GetFollowedCommunitiesResponse> for Oper<GetFollowedCommunities> {
     let communities: Vec<CommunityFollowerView> =
       match CommunityFollowerView::for_user(&conn, user_id) {
         Ok(communities) => communities,
-        Err(_e) => return Err(APIError::err(&self.op, "system_err_login").into()),
+        Err(_e) => return Err(APIError::err("system_err_login").into()),
       };
 
     // Return the jwt
-    Ok(GetFollowedCommunitiesResponse {
-      op: self.op.to_string(),
-      communities,
-    })
+    Ok(GetFollowedCommunitiesResponse { communities })
   }
 }
 
@@ -429,7 +411,7 @@ impl Perform<BanFromCommunityResponse> for Oper<BanFromCommunity> {
 
     let claims = match Claims::decode(&data.auth) {
       Ok(claims) => claims.claims,
-      Err(_e) => return Err(APIError::err(&self.op, "not_logged_in").into()),
+      Err(_e) => return Err(APIError::err("not_logged_in").into()),
     };
 
     let user_id = claims.id;
@@ -442,12 +424,12 @@ impl Perform<BanFromCommunityResponse> for Oper<BanFromCommunity> {
     if data.ban {
       match CommunityUserBan::ban(&conn, &community_user_ban_form) {
         Ok(user) => user,
-        Err(_e) => return Err(APIError::err(&self.op, "community_user_already_banned").into()),
+        Err(_e) => return Err(APIError::err("community_user_already_banned").into()),
       };
     } else {
       match CommunityUserBan::unban(&conn, &community_user_ban_form) {
         Ok(user) => user,
-        Err(_e) => return Err(APIError::err(&self.op, "community_user_already_banned").into()),
+        Err(_e) => return Err(APIError::err("community_user_already_banned").into()),
       };
     }
 
@@ -470,7 +452,6 @@ impl Perform<BanFromCommunityResponse> for Oper<BanFromCommunity> {
     let user_view = UserView::read(&conn, data.user_id)?;
 
     Ok(BanFromCommunityResponse {
-      op: self.op.to_string(),
       user: user_view,
       banned: data.ban,
     })
@@ -483,7 +464,7 @@ impl Perform<AddModToCommunityResponse> for Oper<AddModToCommunity> {
 
     let claims = match Claims::decode(&data.auth) {
       Ok(claims) => claims.claims,
-      Err(_e) => return Err(APIError::err(&self.op, "not_logged_in").into()),
+      Err(_e) => return Err(APIError::err("not_logged_in").into()),
     };
 
     let user_id = claims.id;
@@ -496,16 +477,12 @@ impl Perform<AddModToCommunityResponse> for Oper<AddModToCommunity> {
     if data.added {
       match CommunityModerator::join(&conn, &community_moderator_form) {
         Ok(user) => user,
-        Err(_e) => {
-          return Err(APIError::err(&self.op, "community_moderator_already_exists").into())
-        }
+        Err(_e) => return Err(APIError::err("community_moderator_already_exists").into()),
       };
     } else {
       match CommunityModerator::leave(&conn, &community_moderator_form) {
         Ok(user) => user,
-        Err(_e) => {
-          return Err(APIError::err(&self.op, "community_moderator_already_exists").into())
-        }
+        Err(_e) => return Err(APIError::err("community_moderator_already_exists").into()),
       };
     }
 
@@ -520,10 +497,7 @@ impl Perform<AddModToCommunityResponse> for Oper<AddModToCommunity> {
 
     let moderators = CommunityModeratorView::for_community(&conn, data.community_id)?;
 
-    Ok(AddModToCommunityResponse {
-      op: self.op.to_string(),
-      moderators,
-    })
+    Ok(AddModToCommunityResponse { moderators })
   }
 }
 
@@ -533,7 +507,7 @@ impl Perform<GetCommunityResponse> for Oper<TransferCommunity> {
 
     let claims = match Claims::decode(&data.auth) {
       Ok(claims) => claims.claims,
-      Err(_e) => return Err(APIError::err(&self.op, "not_logged_in").into()),
+      Err(_e) => return Err(APIError::err("not_logged_in").into()),
     };
 
     let user_id = claims.id;
@@ -548,7 +522,7 @@ impl Perform<GetCommunityResponse> for Oper<TransferCommunity> {
 
     // Make sure user is the creator, or an admin
     if user_id != read_community.creator_id && !admins.iter().map(|a| a.id).any(|x| x == user_id) {
-      return Err(APIError::err(&self.op, "not_an_admin").into());
+      return Err(APIError::err("not_an_admin").into());
     }
 
     let community_form = CommunityForm {
@@ -565,7 +539,7 @@ impl Perform<GetCommunityResponse> for Oper<TransferCommunity> {
 
     let _updated_community = match Community::update(&conn, data.community_id, &community_form) {
       Ok(community) => community,
-      Err(_e) => return Err(APIError::err(&self.op, "couldnt_update_community").into()),
+      Err(_e) => return Err(APIError::err("couldnt_update_community").into()),
     };
 
     // You also have to re-do the community_moderator table, reordering it.
@@ -588,9 +562,7 @@ impl Perform<GetCommunityResponse> for Oper<TransferCommunity> {
       let _inserted_community_moderator =
         match CommunityModerator::join(&conn, &community_moderator_form) {
           Ok(user) => user,
-          Err(_e) => {
-            return Err(APIError::err(&self.op, "community_moderator_already_exists").into())
-          }
+          Err(_e) => return Err(APIError::err("community_moderator_already_exists").into()),
         };
     }
 
@@ -605,17 +577,16 @@ impl Perform<GetCommunityResponse> for Oper<TransferCommunity> {
 
     let community_view = match CommunityView::read(&conn, data.community_id, Some(user_id)) {
       Ok(community) => community,
-      Err(_e) => return Err(APIError::err(&self.op, "couldnt_find_community").into()),
+      Err(_e) => return Err(APIError::err("couldnt_find_community").into()),
     };
 
     let moderators = match CommunityModeratorView::for_community(&conn, data.community_id) {
       Ok(moderators) => moderators,
-      Err(_e) => return Err(APIError::err(&self.op, "couldnt_find_community").into()),
+      Err(_e) => return Err(APIError::err("couldnt_find_community").into()),
     };
 
     // Return the jwt
     Ok(GetCommunityResponse {
-      op: self.op.to_string(),
       community: community_view,
       moderators,
       admins,
index e35804476850de62cc00bb2648a8afdaf0bf155d..bee7b8fecb902845067b4e4867a0881a6604ac45 100644 (file)
@@ -26,73 +26,27 @@ pub mod post;
 pub mod site;
 pub mod user;
 
-#[derive(EnumString, ToString, Debug)]
-pub enum UserOperation {
-  Login,
-  Register,
-  CreateCommunity,
-  CreatePost,
-  ListCommunities,
-  ListCategories,
-  GetPost,
-  GetCommunity,
-  CreateComment,
-  EditComment,
-  SaveComment,
-  CreateCommentLike,
-  GetPosts,
-  CreatePostLike,
-  EditPost,
-  SavePost,
-  EditCommunity,
-  FollowCommunity,
-  GetFollowedCommunities,
-  GetUserDetails,
-  GetReplies,
-  GetUserMentions,
-  EditUserMention,
-  GetModlog,
-  BanFromCommunity,
-  AddModToCommunity,
-  CreateSite,
-  EditSite,
-  GetSite,
-  AddAdmin,
-  BanUser,
-  Search,
-  MarkAllAsRead,
-  SaveUserSettings,
-  TransferCommunity,
-  TransferSite,
-  DeleteAccount,
-  PasswordReset,
-  PasswordChange,
-}
-
 #[derive(Fail, Debug)]
-#[fail(display = "{{\"op\":\"{}\", \"error\":\"{}\"}}", op, message)]
+#[fail(display = "{{\"error\":\"{}\"}}", message)]
 pub struct APIError {
-  pub op: String,
   pub message: String,
 }
 
 impl APIError {
-  pub fn err(op: &UserOperation, msg: &str) -> Self {
+  pub fn err(msg: &str) -> Self {
     APIError {
-      op: op.to_string(),
       message: msg.to_string(),
     }
   }
 }
 
 pub struct Oper<T> {
-  op: UserOperation,
   data: T,
 }
 
 impl<T> Oper<T> {
-  pub fn new(op: UserOperation, data: T) -> Oper<T> {
-    Oper { op, data }
+  pub fn new(data: T) -> Oper<T> {
+    Oper { data }
   }
 }
 
index b0fcdd0c1b9f24023b106d1395232462d79ecd58..3f211453c9aec9ccb4a2ed3f97e3262237efadc6 100644 (file)
@@ -14,7 +14,6 @@ pub struct CreatePost {
 
 #[derive(Serialize, Deserialize, Clone)]
 pub struct PostResponse {
-  op: String,
   pub post: PostView,
 }
 
@@ -26,7 +25,6 @@ pub struct GetPost {
 
 #[derive(Serialize, Deserialize)]
 pub struct GetPostResponse {
-  op: String,
   post: PostView,
   comments: Vec<CommentView>,
   community: CommunityView,
@@ -46,7 +44,6 @@ pub struct GetPosts {
 
 #[derive(Serialize, Deserialize)]
 pub struct GetPostsResponse {
-  op: String,
   posts: Vec<PostView>,
 }
 
@@ -59,7 +56,6 @@ pub struct CreatePostLike {
 
 #[derive(Serialize, Deserialize)]
 pub struct CreatePostLikeResponse {
-  op: String,
   post: PostView,
 }
 
@@ -93,23 +89,23 @@ impl Perform<PostResponse> for Oper<CreatePost> {
 
     let claims = match Claims::decode(&data.auth) {
       Ok(claims) => claims.claims,
-      Err(_e) => return Err(APIError::err(&self.op, "not_logged_in").into()),
+      Err(_e) => return Err(APIError::err("not_logged_in").into()),
     };
 
     if has_slurs(&data.name) || (data.body.is_some() && has_slurs(&data.body.to_owned().unwrap())) {
-      return Err(APIError::err(&self.op, "no_slurs").into());
+      return Err(APIError::err("no_slurs").into());
     }
 
     let user_id = claims.id;
 
     // Check for a community ban
     if CommunityUserBanView::get(&conn, user_id, data.community_id).is_ok() {
-      return Err(APIError::err(&self.op, "community_ban").into());
+      return Err(APIError::err("community_ban").into());
     }
 
     // Check for a site ban
     if UserView::read(&conn, user_id)?.banned {
-      return Err(APIError::err(&self.op, "site_ban").into());
+      return Err(APIError::err("site_ban").into());
     }
 
     let post_form = PostForm {
@@ -128,7 +124,7 @@ impl Perform<PostResponse> for Oper<CreatePost> {
 
     let inserted_post = match Post::create(&conn, &post_form) {
       Ok(post) => post,
-      Err(_e) => return Err(APIError::err(&self.op, "couldnt_create_post").into()),
+      Err(_e) => return Err(APIError::err("couldnt_create_post").into()),
     };
 
     // They like their own post by default
@@ -141,19 +137,16 @@ impl Perform<PostResponse> for Oper<CreatePost> {
     // Only add the like if the score isnt 0
     let _inserted_like = match PostLike::like(&conn, &like_form) {
       Ok(like) => like,
-      Err(_e) => return Err(APIError::err(&self.op, "couldnt_like_post").into()),
+      Err(_e) => return Err(APIError::err("couldnt_like_post").into()),
     };
 
     // Refetch the view
     let post_view = match PostView::read(&conn, inserted_post.id, Some(user_id)) {
       Ok(post) => post,
-      Err(_e) => return Err(APIError::err(&self.op, "couldnt_find_post").into()),
+      Err(_e) => return Err(APIError::err("couldnt_find_post").into()),
     };
 
-    Ok(PostResponse {
-      op: self.op.to_string(),
-      post: post_view,
-    })
+    Ok(PostResponse { post: post_view })
   }
 }
 
@@ -174,7 +167,7 @@ impl Perform<GetPostResponse> for Oper<GetPost> {
 
     let post_view = match PostView::read(&conn, data.id, user_id) {
       Ok(post) => post,
-      Err(_e) => return Err(APIError::err(&self.op, "couldnt_find_post").into()),
+      Err(_e) => return Err(APIError::err("couldnt_find_post").into()),
     };
 
     let comments = CommentQueryBuilder::create(&conn)
@@ -195,7 +188,6 @@ impl Perform<GetPostResponse> for Oper<GetPost> {
 
     // Return the jwt
     Ok(GetPostResponse {
-      op: self.op.to_string(),
       post: post_view,
       comments,
       community,
@@ -241,13 +233,10 @@ impl Perform<GetPostsResponse> for Oper<GetPosts> {
       .list()
     {
       Ok(posts) => posts,
-      Err(_e) => return Err(APIError::err(&self.op, "couldnt_get_posts").into()),
+      Err(_e) => return Err(APIError::err("couldnt_get_posts").into()),
     };
 
-    Ok(GetPostsResponse {
-      op: self.op.to_string(),
-      posts,
-    })
+    Ok(GetPostsResponse { posts })
   }
 }
 
@@ -257,7 +246,7 @@ impl Perform<CreatePostLikeResponse> for Oper<CreatePostLike> {
 
     let claims = match Claims::decode(&data.auth) {
       Ok(claims) => claims.claims,
-      Err(_e) => return Err(APIError::err(&self.op, "not_logged_in").into()),
+      Err(_e) => return Err(APIError::err("not_logged_in").into()),
     };
 
     let user_id = claims.id;
@@ -266,19 +255,19 @@ impl Perform<CreatePostLikeResponse> for Oper<CreatePostLike> {
     if data.score == -1 {
       let site = SiteView::read(&conn)?;
       if !site.enable_downvotes {
-        return Err(APIError::err(&self.op, "downvotes_disabled").into());
+        return Err(APIError::err("downvotes_disabled").into());
       }
     }
 
     // Check for a community ban
     let post = Post::read(&conn, data.post_id)?;
     if CommunityUserBanView::get(&conn, user_id, post.community_id).is_ok() {
-      return Err(APIError::err(&self.op, "community_ban").into());
+      return Err(APIError::err("community_ban").into());
     }
 
     // Check for a site ban
     if UserView::read(&conn, user_id)?.banned {
-      return Err(APIError::err(&self.op, "site_ban").into());
+      return Err(APIError::err("site_ban").into());
     }
 
     let like_form = PostLikeForm {
@@ -295,20 +284,17 @@ impl Perform<CreatePostLikeResponse> for Oper<CreatePostLike> {
     if do_add {
       let _inserted_like = match PostLike::like(&conn, &like_form) {
         Ok(like) => like,
-        Err(_e) => return Err(APIError::err(&self.op, "couldnt_like_post").into()),
+        Err(_e) => return Err(APIError::err("couldnt_like_post").into()),
       };
     }
 
     let post_view = match PostView::read(&conn, data.post_id, Some(user_id)) {
       Ok(post) => post,
-      Err(_e) => return Err(APIError::err(&self.op, "couldnt_find_post").into()),
+      Err(_e) => return Err(APIError::err("couldnt_find_post").into()),
     };
 
     // just output the score
-    Ok(CreatePostLikeResponse {
-      op: self.op.to_string(),
-      post: post_view,
-    })
+    Ok(CreatePostLikeResponse { post: post_view })
   }
 }
 
@@ -316,12 +302,12 @@ impl Perform<PostResponse> for Oper<EditPost> {
   fn perform(&self, conn: &PgConnection) -> Result<PostResponse, Error> {
     let data: &EditPost = &self.data;
     if has_slurs(&data.name) || (data.body.is_some() && has_slurs(&data.body.to_owned().unwrap())) {
-      return Err(APIError::err(&self.op, "no_slurs").into());
+      return Err(APIError::err("no_slurs").into());
     }
 
     let claims = match Claims::decode(&data.auth) {
       Ok(claims) => claims.claims,
-      Err(_e) => return Err(APIError::err(&self.op, "not_logged_in").into()),
+      Err(_e) => return Err(APIError::err("not_logged_in").into()),
     };
 
     let user_id = claims.id;
@@ -336,17 +322,17 @@ impl Perform<PostResponse> for Oper<EditPost> {
     );
     editors.append(&mut UserView::admins(&conn)?.into_iter().map(|a| a.id).collect());
     if !editors.contains(&user_id) {
-      return Err(APIError::err(&self.op, "no_post_edit_allowed").into());
+      return Err(APIError::err("no_post_edit_allowed").into());
     }
 
     // Check for a community ban
     if CommunityUserBanView::get(&conn, user_id, data.community_id).is_ok() {
-      return Err(APIError::err(&self.op, "community_ban").into());
+      return Err(APIError::err("community_ban").into());
     }
 
     // Check for a site ban
     if UserView::read(&conn, user_id)?.banned {
-      return Err(APIError::err(&self.op, "site_ban").into());
+      return Err(APIError::err("site_ban").into());
     }
 
     let post_form = PostForm {
@@ -365,7 +351,7 @@ impl Perform<PostResponse> for Oper<EditPost> {
 
     let _updated_post = match Post::update(&conn, data.edit_id, &post_form) {
       Ok(post) => post,
-      Err(_e) => return Err(APIError::err(&self.op, "couldnt_update_post").into()),
+      Err(_e) => return Err(APIError::err("couldnt_update_post").into()),
     };
 
     // Mod tables
@@ -399,10 +385,7 @@ impl Perform<PostResponse> for Oper<EditPost> {
 
     let post_view = PostView::read(&conn, data.edit_id, Some(user_id))?;
 
-    Ok(PostResponse {
-      op: self.op.to_string(),
-      post: post_view,
-    })
+    Ok(PostResponse { post: post_view })
   }
 }
 
@@ -412,7 +395,7 @@ impl Perform<PostResponse> for Oper<SavePost> {
 
     let claims = match Claims::decode(&data.auth) {
       Ok(claims) => claims.claims,
-      Err(_e) => return Err(APIError::err(&self.op, "not_logged_in").into()),
+      Err(_e) => return Err(APIError::err("not_logged_in").into()),
     };
 
     let user_id = claims.id;
@@ -425,20 +408,17 @@ impl Perform<PostResponse> for Oper<SavePost> {
     if data.save {
       match PostSaved::save(&conn, &post_saved_form) {
         Ok(post) => post,
-        Err(_e) => return Err(APIError::err(&self.op, "couldnt_save_post").into()),
+        Err(_e) => return Err(APIError::err("couldnt_save_post").into()),
       };
     } else {
       match PostSaved::unsave(&conn, &post_saved_form) {
         Ok(post) => post,
-        Err(_e) => return Err(APIError::err(&self.op, "couldnt_save_post").into()),
+        Err(_e) => return Err(APIError::err("couldnt_save_post").into()),
       };
     }
 
     let post_view = PostView::read(&conn, data.post_id, Some(user_id))?;
 
-    Ok(PostResponse {
-      op: self.op.to_string(),
-      post: post_view,
-    })
+    Ok(PostResponse { post: post_view })
   }
 }
index a189a0308866dfc48897c111446cc46e18a20491..1291891b46562929208cc8dd9088ecd3e511017d 100644 (file)
@@ -7,7 +7,6 @@ pub struct ListCategories;
 
 #[derive(Serialize, Deserialize)]
 pub struct ListCategoriesResponse {
-  op: String,
   categories: Vec<Category>,
 }
 
@@ -23,7 +22,6 @@ pub struct Search {
 
 #[derive(Serialize, Deserialize)]
 pub struct SearchResponse {
-  op: String,
   type_: String,
   comments: Vec<CommentView>,
   posts: Vec<PostView>,
@@ -41,7 +39,6 @@ pub struct GetModlog {
 
 #[derive(Serialize, Deserialize)]
 pub struct GetModlogResponse {
-  op: String,
   removed_posts: Vec<ModRemovePostView>,
   locked_posts: Vec<ModLockPostView>,
   stickied_posts: Vec<ModStickyPostView>,
@@ -78,13 +75,11 @@ pub struct GetSite;
 
 #[derive(Serialize, Deserialize)]
 pub struct SiteResponse {
-  op: String,
   site: SiteView,
 }
 
 #[derive(Serialize, Deserialize)]
 pub struct GetSiteResponse {
-  op: String,
   site: Option<SiteView>,
   admins: Vec<UserView>,
   banned: Vec<UserView>,
@@ -104,10 +99,7 @@ impl Perform<ListCategoriesResponse> for Oper<ListCategories> {
     let categories: Vec<Category> = Category::list_all(&conn)?;
 
     // Return the jwt
-    Ok(ListCategoriesResponse {
-      op: self.op.to_string(),
-      categories,
-    })
+    Ok(ListCategoriesResponse { categories })
   }
 }
 
@@ -171,7 +163,6 @@ impl Perform<GetModlogResponse> for Oper<GetModlog> {
 
     // Return the jwt
     Ok(GetModlogResponse {
-      op: self.op.to_string(),
       removed_posts,
       locked_posts,
       stickied_posts,
@@ -191,20 +182,20 @@ impl Perform<SiteResponse> for Oper<CreateSite> {
 
     let claims = match Claims::decode(&data.auth) {
       Ok(claims) => claims.claims,
-      Err(_e) => return Err(APIError::err(&self.op, "not_logged_in").into()),
+      Err(_e) => return Err(APIError::err("not_logged_in").into()),
     };
 
     if has_slurs(&data.name)
       || (data.description.is_some() && has_slurs(&data.description.to_owned().unwrap()))
     {
-      return Err(APIError::err(&self.op, "no_slurs").into());
+      return Err(APIError::err("no_slurs").into());
     }
 
     let user_id = claims.id;
 
     // Make sure user is an admin
     if !UserView::read(&conn, user_id)?.admin {
-      return Err(APIError::err(&self.op, "not_an_admin").into());
+      return Err(APIError::err("not_an_admin").into());
     }
 
     let site_form = SiteForm {
@@ -219,15 +210,12 @@ impl Perform<SiteResponse> for Oper<CreateSite> {
 
     match Site::create(&conn, &site_form) {
       Ok(site) => site,
-      Err(_e) => return Err(APIError::err(&self.op, "site_already_exists").into()),
+      Err(_e) => return Err(APIError::err("site_already_exists").into()),
     };
 
     let site_view = SiteView::read(&conn)?;
 
-    Ok(SiteResponse {
-      op: self.op.to_string(),
-      site: site_view,
-    })
+    Ok(SiteResponse { site: site_view })
   }
 }
 
@@ -237,20 +225,20 @@ impl Perform<SiteResponse> for Oper<EditSite> {
 
     let claims = match Claims::decode(&data.auth) {
       Ok(claims) => claims.claims,
-      Err(_e) => return Err(APIError::err(&self.op, "not_logged_in").into()),
+      Err(_e) => return Err(APIError::err("not_logged_in").into()),
     };
 
     if has_slurs(&data.name)
       || (data.description.is_some() && has_slurs(&data.description.to_owned().unwrap()))
     {
-      return Err(APIError::err(&self.op, "no_slurs").into());
+      return Err(APIError::err("no_slurs").into());
     }
 
     let user_id = claims.id;
 
     // Make sure user is an admin
     if !UserView::read(&conn, user_id)?.admin {
-      return Err(APIError::err(&self.op, "not_an_admin").into());
+      return Err(APIError::err("not_an_admin").into());
     }
 
     let found_site = Site::read(&conn, 1)?;
@@ -267,15 +255,12 @@ impl Perform<SiteResponse> for Oper<EditSite> {
 
     match Site::update(&conn, 1, &site_form) {
       Ok(site) => site,
-      Err(_e) => return Err(APIError::err(&self.op, "couldnt_update_site").into()),
+      Err(_e) => return Err(APIError::err("couldnt_update_site").into()),
     };
 
     let site_view = SiteView::read(&conn)?;
 
-    Ok(SiteResponse {
-      op: self.op.to_string(),
-      site: site_view,
-    })
+    Ok(SiteResponse { site: site_view })
   }
 }
 
@@ -300,7 +285,6 @@ impl Perform<GetSiteResponse> for Oper<GetSite> {
     let banned = UserView::banned(&conn)?;
 
     Ok(GetSiteResponse {
-      op: self.op.to_string(),
       site: site_view,
       admins,
       banned,
@@ -403,7 +387,6 @@ impl Perform<SearchResponse> for Oper<Search> {
 
     // Return the jwt
     Ok(SearchResponse {
-      op: self.op.to_string(),
       type_: data.type_.to_owned(),
       comments,
       posts,
@@ -419,7 +402,7 @@ impl Perform<GetSiteResponse> for Oper<TransferSite> {
 
     let claims = match Claims::decode(&data.auth) {
       Ok(claims) => claims.claims,
-      Err(_e) => return Err(APIError::err(&self.op, "not_logged_in").into()),
+      Err(_e) => return Err(APIError::err("not_logged_in").into()),
     };
 
     let user_id = claims.id;
@@ -428,7 +411,7 @@ impl Perform<GetSiteResponse> for Oper<TransferSite> {
 
     // Make sure user is the creator
     if read_site.creator_id != user_id {
-      return Err(APIError::err(&self.op, "not_an_admin").into());
+      return Err(APIError::err("not_an_admin").into());
     }
 
     let site_form = SiteForm {
@@ -443,7 +426,7 @@ impl Perform<GetSiteResponse> for Oper<TransferSite> {
 
     match Site::update(&conn, 1, &site_form) {
       Ok(site) => site,
-      Err(_e) => return Err(APIError::err(&self.op, "couldnt_update_site").into()),
+      Err(_e) => return Err(APIError::err("couldnt_update_site").into()),
     };
 
     // Mod tables
@@ -468,7 +451,6 @@ impl Perform<GetSiteResponse> for Oper<TransferSite> {
     let banned = UserView::banned(&conn)?;
 
     Ok(GetSiteResponse {
-      op: self.op.to_string(),
       site: Some(site_view),
       admins,
       banned,
index ac700acad53f73bdd4affbd9fd39dfe857a7fede..e1ddb1caeda96d237f6dfcbee90ad83e22b784aa 100644 (file)
@@ -40,7 +40,6 @@ pub struct SaveUserSettings {
 
 #[derive(Serialize, Deserialize)]
 pub struct LoginResponse {
-  op: String,
   jwt: String,
 }
 
@@ -58,7 +57,6 @@ pub struct GetUserDetails {
 
 #[derive(Serialize, Deserialize)]
 pub struct GetUserDetailsResponse {
-  op: String,
   user: UserView,
   follows: Vec<CommunityFollowerView>,
   moderates: Vec<CommunityModeratorView>,
@@ -69,13 +67,11 @@ pub struct GetUserDetailsResponse {
 
 #[derive(Serialize, Deserialize)]
 pub struct GetRepliesResponse {
-  op: String,
   replies: Vec<ReplyView>,
 }
 
 #[derive(Serialize, Deserialize)]
 pub struct GetUserMentionsResponse {
-  op: String,
   mentions: Vec<UserMentionView>,
 }
 
@@ -93,7 +89,6 @@ pub struct AddAdmin {
 
 #[derive(Serialize, Deserialize)]
 pub struct AddAdminResponse {
-  op: String,
   admins: Vec<UserView>,
 }
 
@@ -108,7 +103,6 @@ pub struct BanUser {
 
 #[derive(Serialize, Deserialize)]
 pub struct BanUserResponse {
-  op: String,
   user: UserView,
   banned: bool,
 }
@@ -140,7 +134,6 @@ pub struct EditUserMention {
 
 #[derive(Serialize, Deserialize, Clone)]
 pub struct UserMentionResponse {
-  op: String,
   mention: UserMentionView,
 }
 
@@ -156,9 +149,7 @@ pub struct PasswordReset {
 }
 
 #[derive(Serialize, Deserialize, Clone)]
-pub struct PasswordResetResponse {
-  op: String,
-}
+pub struct PasswordResetResponse {}
 
 #[derive(Serialize, Deserialize)]
 pub struct PasswordChange {
@@ -174,20 +165,17 @@ impl Perform<LoginResponse> for Oper<Login> {
     // Fetch that username / email
     let user: User_ = match User_::find_by_email_or_username(&conn, &data.username_or_email) {
       Ok(user) => user,
-      Err(_e) => return Err(APIError::err(&self.op, "couldnt_find_that_username_or_email").into()),
+      Err(_e) => return Err(APIError::err("couldnt_find_that_username_or_email").into()),
     };
 
     // Verify the password
     let valid: bool = verify(&data.password, &user.password_encrypted).unwrap_or(false);
     if !valid {
-      return Err(APIError::err(&self.op, "password_incorrect").into());
+      return Err(APIError::err("password_incorrect").into());
     }
 
     // Return the jwt
-    Ok(LoginResponse {
-      op: self.op.to_string(),
-      jwt: user.jwt(),
-    })
+    Ok(LoginResponse { jwt: user.jwt() })
   }
 }
 
@@ -198,22 +186,22 @@ impl Perform<LoginResponse> for Oper<Register> {
     // Make sure site has open registration
     if let Ok(site) = SiteView::read(&conn) {
       if !site.open_registration {
-        return Err(APIError::err(&self.op, "registration_closed").into());
+        return Err(APIError::err("registration_closed").into());
       }
     }
 
     // Make sure passwords match
     if data.password != data.password_verify {
-      return Err(APIError::err(&self.op, "passwords_dont_match").into());
+      return Err(APIError::err("passwords_dont_match").into());
     }
 
     if has_slurs(&data.username) {
-      return Err(APIError::err(&self.op, "no_slurs").into());
+      return Err(APIError::err("no_slurs").into());
     }
 
     // Make sure there are no admins
     if data.admin && !UserView::admins(&conn)?.is_empty() {
-      return Err(APIError::err(&self.op, "admin_already_created").into());
+      return Err(APIError::err("admin_already_created").into());
     }
 
     // Register the new user
@@ -248,7 +236,7 @@ impl Perform<LoginResponse> for Oper<Register> {
           "user_already_exists"
         };
 
-        return Err(APIError::err(&self.op, err_type).into());
+        return Err(APIError::err(err_type).into());
       }
     };
 
@@ -280,7 +268,7 @@ impl Perform<LoginResponse> for Oper<Register> {
     let _inserted_community_follower =
       match CommunityFollower::follow(&conn, &community_follower_form) {
         Ok(user) => user,
-        Err(_e) => return Err(APIError::err(&self.op, "community_follower_already_exists").into()),
+        Err(_e) => return Err(APIError::err("community_follower_already_exists").into()),
       };
 
     // If its an admin, add them as a mod and follower to main
@@ -293,15 +281,12 @@ impl Perform<LoginResponse> for Oper<Register> {
       let _inserted_community_moderator =
         match CommunityModerator::join(&conn, &community_moderator_form) {
           Ok(user) => user,
-          Err(_e) => {
-            return Err(APIError::err(&self.op, "community_moderator_already_exists").into())
-          }
+          Err(_e) => return Err(APIError::err("community_moderator_already_exists").into()),
         };
     }
 
     // Return the jwt
     Ok(LoginResponse {
-      op: self.op.to_string(),
       jwt: inserted_user.jwt(),
     })
   }
@@ -313,7 +298,7 @@ impl Perform<LoginResponse> for Oper<SaveUserSettings> {
 
     let claims = match Claims::decode(&data.auth) {
       Ok(claims) => claims.claims,
-      Err(_e) => return Err(APIError::err(&self.op, "not_logged_in").into()),
+      Err(_e) => return Err(APIError::err("not_logged_in").into()),
     };
 
     let user_id = claims.id;
@@ -331,7 +316,7 @@ impl Perform<LoginResponse> for Oper<SaveUserSettings> {
           Some(new_password_verify) => {
             // Make sure passwords match
             if new_password != new_password_verify {
-              return Err(APIError::err(&self.op, "passwords_dont_match").into());
+              return Err(APIError::err("passwords_dont_match").into());
             }
 
             // Check the old password
@@ -340,14 +325,14 @@ impl Perform<LoginResponse> for Oper<SaveUserSettings> {
                 let valid: bool =
                   verify(old_password, &read_user.password_encrypted).unwrap_or(false);
                 if !valid {
-                  return Err(APIError::err(&self.op, "password_incorrect").into());
+                  return Err(APIError::err("password_incorrect").into());
                 }
                 User_::update_password(&conn, user_id, &new_password)?.password_encrypted
               }
-              None => return Err(APIError::err(&self.op, "password_incorrect").into()),
+              None => return Err(APIError::err("password_incorrect").into()),
             }
           }
-          None => return Err(APIError::err(&self.op, "passwords_dont_match").into()),
+          None => return Err(APIError::err("passwords_dont_match").into()),
         }
       }
       None => read_user.password_encrypted,
@@ -383,13 +368,12 @@ impl Perform<LoginResponse> for Oper<SaveUserSettings> {
           "user_already_exists"
         };
 
-        return Err(APIError::err(&self.op, err_type).into());
+        return Err(APIError::err(err_type).into());
       }
     };
 
     // Return the jwt
     Ok(LoginResponse {
-      op: self.op.to_string(),
       jwt: updated_user.jwt(),
     })
   }
@@ -430,9 +414,7 @@ impl Perform<GetUserDetailsResponse> for Oper<GetUserDetails> {
             .unwrap_or_else(|| "admin".to_string()),
         ) {
           Ok(user) => user.id,
-          Err(_e) => {
-            return Err(APIError::err(&self.op, "couldnt_find_that_username_or_email").into())
-          }
+          Err(_e) => return Err(APIError::err("couldnt_find_that_username_or_email").into()),
         }
       }
     };
@@ -475,7 +457,6 @@ impl Perform<GetUserDetailsResponse> for Oper<GetUserDetails> {
 
     // Return the jwt
     Ok(GetUserDetailsResponse {
-      op: self.op.to_string(),
       user: user_view,
       follows,
       moderates,
@@ -492,14 +473,14 @@ impl Perform<AddAdminResponse> for Oper<AddAdmin> {
 
     let claims = match Claims::decode(&data.auth) {
       Ok(claims) => claims.claims,
-      Err(_e) => return Err(APIError::err(&self.op, "not_logged_in").into()),
+      Err(_e) => return Err(APIError::err("not_logged_in").into()),
     };
 
     let user_id = claims.id;
 
     // Make sure user is an admin
     if !UserView::read(&conn, user_id)?.admin {
-      return Err(APIError::err(&self.op, "not_an_admin").into());
+      return Err(APIError::err("not_an_admin").into());
     }
 
     let read_user = User_::read(&conn, data.user_id)?;
@@ -525,7 +506,7 @@ impl Perform<AddAdminResponse> for Oper<AddAdmin> {
 
     match User_::update(&conn, data.user_id, &user_form) {
       Ok(user) => user,
-      Err(_e) => return Err(APIError::err(&self.op, "couldnt_update_user").into()),
+      Err(_e) => return Err(APIError::err("couldnt_update_user").into()),
     };
 
     // Mod tables
@@ -543,10 +524,7 @@ impl Perform<AddAdminResponse> for Oper<AddAdmin> {
     let creator_user = admins.remove(creator_index);
     admins.insert(0, creator_user);
 
-    Ok(AddAdminResponse {
-      op: self.op.to_string(),
-      admins,
-    })
+    Ok(AddAdminResponse { admins })
   }
 }
 
@@ -556,14 +534,14 @@ impl Perform<BanUserResponse> for Oper<BanUser> {
 
     let claims = match Claims::decode(&data.auth) {
       Ok(claims) => claims.claims,
-      Err(_e) => return Err(APIError::err(&self.op, "not_logged_in").into()),
+      Err(_e) => return Err(APIError::err("not_logged_in").into()),
     };
 
     let user_id = claims.id;
 
     // Make sure user is an admin
     if !UserView::read(&conn, user_id)?.admin {
-      return Err(APIError::err(&self.op, "not_an_admin").into());
+      return Err(APIError::err("not_an_admin").into());
     }
 
     let read_user = User_::read(&conn, data.user_id)?;
@@ -589,7 +567,7 @@ impl Perform<BanUserResponse> for Oper<BanUser> {
 
     match User_::update(&conn, data.user_id, &user_form) {
       Ok(user) => user,
-      Err(_e) => return Err(APIError::err(&self.op, "couldnt_update_user").into()),
+      Err(_e) => return Err(APIError::err("couldnt_update_user").into()),
     };
 
     // Mod tables
@@ -611,7 +589,6 @@ impl Perform<BanUserResponse> for Oper<BanUser> {
     let user_view = UserView::read(&conn, data.user_id)?;
 
     Ok(BanUserResponse {
-      op: self.op.to_string(),
       user: user_view,
       banned: data.ban,
     })
@@ -624,7 +601,7 @@ impl Perform<GetRepliesResponse> for Oper<GetReplies> {
 
     let claims = match Claims::decode(&data.auth) {
       Ok(claims) => claims.claims,
-      Err(_e) => return Err(APIError::err(&self.op, "not_logged_in").into()),
+      Err(_e) => return Err(APIError::err("not_logged_in").into()),
     };
 
     let user_id = claims.id;
@@ -638,10 +615,7 @@ impl Perform<GetRepliesResponse> for Oper<GetReplies> {
       .limit(data.limit)
       .list()?;
 
-    Ok(GetRepliesResponse {
-      op: self.op.to_string(),
-      replies,
-    })
+    Ok(GetRepliesResponse { replies })
   }
 }
 
@@ -651,7 +625,7 @@ impl Perform<GetUserMentionsResponse> for Oper<GetUserMentions> {
 
     let claims = match Claims::decode(&data.auth) {
       Ok(claims) => claims.claims,
-      Err(_e) => return Err(APIError::err(&self.op, "not_logged_in").into()),
+      Err(_e) => return Err(APIError::err("not_logged_in").into()),
     };
 
     let user_id = claims.id;
@@ -665,10 +639,7 @@ impl Perform<GetUserMentionsResponse> for Oper<GetUserMentions> {
       .limit(data.limit)
       .list()?;
 
-    Ok(GetUserMentionsResponse {
-      op: self.op.to_string(),
-      mentions,
-    })
+    Ok(GetUserMentionsResponse { mentions })
   }
 }
 
@@ -678,7 +649,7 @@ impl Perform<UserMentionResponse> for Oper<EditUserMention> {
 
     let claims = match Claims::decode(&data.auth) {
       Ok(claims) => claims.claims,
-      Err(_e) => return Err(APIError::err(&self.op, "not_logged_in").into()),
+      Err(_e) => return Err(APIError::err("not_logged_in").into()),
     };
 
     let user_id = claims.id;
@@ -694,13 +665,12 @@ impl Perform<UserMentionResponse> for Oper<EditUserMention> {
     let _updated_user_mention =
       match UserMention::update(&conn, user_mention.id, &user_mention_form) {
         Ok(comment) => comment,
-        Err(_e) => return Err(APIError::err(&self.op, "couldnt_update_comment").into()),
+        Err(_e) => return Err(APIError::err("couldnt_update_comment").into()),
       };
 
     let user_mention_view = UserMentionView::read(&conn, user_mention.id, user_id)?;
 
     Ok(UserMentionResponse {
-      op: self.op.to_string(),
       mention: user_mention_view,
     })
   }
@@ -712,7 +682,7 @@ impl Perform<GetRepliesResponse> for Oper<MarkAllAsRead> {
 
     let claims = match Claims::decode(&data.auth) {
       Ok(claims) => claims.claims,
-      Err(_e) => return Err(APIError::err(&self.op, "not_logged_in").into()),
+      Err(_e) => return Err(APIError::err("not_logged_in").into()),
     };
 
     let user_id = claims.id;
@@ -737,7 +707,7 @@ impl Perform<GetRepliesResponse> for Oper<MarkAllAsRead> {
 
       let _updated_comment = match Comment::update(&conn, reply.id, &comment_form) {
         Ok(comment) => comment,
-        Err(_e) => return Err(APIError::err(&self.op, "couldnt_update_comment").into()),
+        Err(_e) => return Err(APIError::err("couldnt_update_comment").into()),
       };
     }
 
@@ -758,14 +728,11 @@ impl Perform<GetRepliesResponse> for Oper<MarkAllAsRead> {
       let _updated_mention =
         match UserMention::update(&conn, mention.user_mention_id, &mention_form) {
           Ok(mention) => mention,
-          Err(_e) => return Err(APIError::err(&self.op, "couldnt_update_comment").into()),
+          Err(_e) => return Err(APIError::err("couldnt_update_comment").into()),
         };
     }
 
-    Ok(GetRepliesResponse {
-      op: self.op.to_string(),
-      replies: vec![],
-    })
+    Ok(GetRepliesResponse { replies: vec![] })
   }
 }
 
@@ -775,7 +742,7 @@ impl Perform<LoginResponse> for Oper<DeleteAccount> {
 
     let claims = match Claims::decode(&data.auth) {
       Ok(claims) => claims.claims,
-      Err(_e) => return Err(APIError::err(&self.op, "not_logged_in").into()),
+      Err(_e) => return Err(APIError::err("not_logged_in").into()),
     };
 
     let user_id = claims.id;
@@ -785,7 +752,7 @@ impl Perform<LoginResponse> for Oper<DeleteAccount> {
     // Verify the password
     let valid: bool = verify(&data.password, &user.password_encrypted).unwrap_or(false);
     if !valid {
-      return Err(APIError::err(&self.op, "password_incorrect").into());
+      return Err(APIError::err("password_incorrect").into());
     }
 
     // Comments
@@ -808,7 +775,7 @@ impl Perform<LoginResponse> for Oper<DeleteAccount> {
 
       let _updated_comment = match Comment::update(&conn, comment.id, &comment_form) {
         Ok(comment) => comment,
-        Err(_e) => return Err(APIError::err(&self.op, "couldnt_update_comment").into()),
+        Err(_e) => return Err(APIError::err("couldnt_update_comment").into()),
       };
     }
 
@@ -836,12 +803,11 @@ impl Perform<LoginResponse> for Oper<DeleteAccount> {
 
       let _updated_post = match Post::update(&conn, post.id, &post_form) {
         Ok(post) => post,
-        Err(_e) => return Err(APIError::err(&self.op, "couldnt_update_post").into()),
+        Err(_e) => return Err(APIError::err("couldnt_update_post").into()),
       };
     }
 
     Ok(LoginResponse {
-      op: self.op.to_string(),
       jwt: data.auth.to_owned(),
     })
   }
@@ -854,7 +820,7 @@ impl Perform<PasswordResetResponse> for Oper<PasswordReset> {
     // Fetch that email
     let user: User_ = match User_::find_by_email(&conn, &data.email) {
       Ok(user) => user,
-      Err(_e) => return Err(APIError::err(&self.op, "couldnt_find_that_username_or_email").into()),
+      Err(_e) => return Err(APIError::err("couldnt_find_that_username_or_email").into()),
     };
 
     // Generate a random token
@@ -871,12 +837,10 @@ impl Perform<PasswordResetResponse> for Oper<PasswordReset> {
     let html = &format!("<h1>Password Reset Request for {}</h1><br><a href={}/password_change/{}>Click here to reset your password</a>", user.name, hostname, &token);
     match send_email(subject, user_email, &user.name, html) {
       Ok(_o) => _o,
-      Err(_e) => return Err(APIError::err(&self.op, &_e).into()),
+      Err(_e) => return Err(APIError::err(&_e).into()),
     };
 
-    Ok(PasswordResetResponse {
-      op: self.op.to_string(),
-    })
+    Ok(PasswordResetResponse {})
   }
 }
 
@@ -889,18 +853,17 @@ impl Perform<LoginResponse> for Oper<PasswordChange> {
 
     // Make sure passwords match
     if data.password != data.password_verify {
-      return Err(APIError::err(&self.op, "passwords_dont_match").into());
+      return Err(APIError::err("passwords_dont_match").into());
     }
 
     // Update the user with the new password
     let updated_user = match User_::update_password(&conn, user_id, &data.password) {
       Ok(user) => user,
-      Err(_e) => return Err(APIError::err(&self.op, "couldnt_update_user").into()),
+      Err(_e) => return Err(APIError::err("couldnt_update_user").into()),
     };
 
     // Return the jwt
     Ok(LoginResponse {
-      op: self.op.to_string(),
       jwt: updated_user.jwt(),
     })
   }
index 11919b8cc84bd5df4a97119a4f98289787af9156..70e686883351b00c936b47e545ed67b2daa6f068 100644 (file)
@@ -1,7 +1,8 @@
-use crate::api::community::{
-  GetCommunity, GetCommunityResponse, ListCommunities, ListCommunitiesResponse,
-};
-use crate::api::UserOperation;
+use crate::api::comment::*;
+use crate::api::community::*;
+use crate::api::post::*;
+use crate::api::site::*;
+use crate::api::user::*;
 use crate::api::{Oper, Perform};
 use actix_web::{web, HttpResponse};
 use diesel::r2d2::{ConnectionManager, Pool};
@@ -13,26 +14,165 @@ type DbParam = web::Data<Pool<ConnectionManager<PgConnection>>>;
 
 pub fn config(cfg: &mut web::ServiceConfig) {
   cfg
-    // TODO: need to repeat this for every endpoint
+    .route(
+      "/api/v1/login",
+      web::post().to(route::<Login, LoginResponse>),
+    )
+    .route(
+      "/api/v1/register",
+      web::post().to(route::<Register, LoginResponse>),
+    )
+    .route(
+      "/api/v1/create_community",
+      web::post().to(route::<CreateCommunity, CommunityResponse>),
+    )
+    .route(
+      "/api/v1/create_post",
+      web::post().to(route::<CreatePost, PostResponse>),
+    )
     .route(
       "/api/v1/list_communities",
-      web::get().to(
-        route::<ListCommunities, ListCommunitiesResponse>(UserOperation::ListCommunities)
-      ),
+      web::get().to(route::<ListCommunities, ListCommunitiesResponse>),
+    )
+    .route(
+      "/api/v1/list_categories",
+      web::get().to(route::<ListCategories, ListCategoriesResponse>),
+    )
+    .route(
+      "/api/v1/get_post",
+      web::get().to(route::<GetPost, GetPostResponse>),
     )
     .route(
       "/api/v1/get_community",
-      web::get().to(route::<GetCommunity, GetCommunityResponse>(
-        UserOperation::GetCommunity,
-      )),
+      web::get().to(route::<GetCommunity, GetCommunityResponse>),
+    )
+    .route(
+      "/api/v1/create_communent",
+      web::post().to(route::<CreateComment, CommentResponse>),
+    )
+    .route(
+      "/api/v1/edit_comment",
+      web::post().to(route::<EditComment, CommentResponse>),
+    )
+    .route(
+      "/api/v1/save_comment",
+      web::post().to(route::<SaveComment, CommentResponse>),
+    )
+    .route(
+      "/api/v1/create_comment_like",
+      web::post().to(route::<CreateCommentLike, CommentResponse>),
+    )
+    .route(
+      "/api/v1/get_posts",
+      web::get().to(route::<GetPosts, GetPostsResponse>),
+    )
+    .route(
+      "/api/v1/create_post_like",
+      web::post().to(route::<CreatePostLike, CreatePostLikeResponse>),
+    )
+    .route(
+      "/api/v1/edit_post",
+      web::post().to(route::<EditPost, PostResponse>),
+    )
+    .route(
+      "/api/v1/save_post",
+      web::post().to(route::<SavePost, PostResponse>),
+    )
+    .route(
+      "/api/v1/edit_community",
+      web::post().to(route::<EditCommunity, CommunityResponse>),
+    )
+    .route(
+      "/api/v1/follow_community",
+      web::post().to(route::<FollowCommunity, CommunityResponse>),
+    )
+    .route(
+      "/api/v1/get_followed_communities",
+      web::get().to(route::<GetFollowedCommunities, GetFollowedCommunitiesResponse>),
+    )
+    .route(
+      "/api/v1/get_user_details",
+      web::get().to(route::<GetUserDetails, GetUserDetailsResponse>),
+    )
+    .route(
+      "/api/v1/get_replies",
+      web::get().to(route::<GetReplies, GetRepliesResponse>),
+    )
+    .route(
+      "/api/v1/get_user_mentions",
+      web::get().to(route::<GetUserMentions, GetUserMentionsResponse>),
+    )
+    .route(
+      "/api/v1/edit_user_mention",
+      web::post().to(route::<EditUserMention, UserMentionResponse>),
+    )
+    .route(
+      "/api/v1/get_modlog",
+      web::get().to(route::<GetModlog, GetModlogResponse>),
+    )
+    .route(
+      "/api/v1/ban_from_community",
+      web::post().to(route::<BanFromCommunity, BanFromCommunityResponse>),
+    )
+    .route(
+      "/api/v1/add_mod_to_community",
+      web::post().to(route::<AddModToCommunity, AddModToCommunityResponse>),
+    )
+    .route(
+      "/api/v1/create_site",
+      web::post().to(route::<CreateSite, SiteResponse>),
+    )
+    .route(
+      "/api/v1/edit_site",
+      web::post().to(route::<EditSite, SiteResponse>),
+    )
+    .route(
+      "/api/v1/get_site",
+      web::get().to(route::<GetSite, GetSiteResponse>),
+    )
+    .route(
+      "/api/v1/add_admin",
+      web::post().to(route::<AddAdmin, AddAdminResponse>),
+    )
+    .route(
+      "/api/v1/ban_user",
+      web::post().to(route::<BanUser, BanUserResponse>),
+    )
+    .route(
+      "/api/v1/search",
+      web::post().to(route::<Search, SearchResponse>),
+    )
+    .route(
+      "/api/v1/mark_all_as_read",
+      web::post().to(route::<MarkAllAsRead, GetRepliesResponse>),
+    )
+    .route(
+      "/api/v1/save_user_settings",
+      web::post().to(route::<SaveUserSettings, LoginResponse>),
+    )
+    .route(
+      "/api/v1/transfer_community",
+      web::post().to(route::<TransferCommunity, GetCommunityResponse>),
+    )
+    .route(
+      "/api/v1/transfer_site",
+      web::post().to(route::<TransferSite, GetSiteResponse>),
+    )
+    .route(
+      "/api/v1/delete_account",
+      web::post().to(route::<DeleteAccount, LoginResponse>),
+    )
+    .route(
+      "/api/v1/password_reset",
+      web::post().to(route::<PasswordReset, PasswordResetResponse>),
+    )
+    .route(
+      "/api/v1/password_change",
+      web::post().to(route::<PasswordChange, LoginResponse>),
     );
 }
 
-fn perform<Request, Response>(
-  op: UserOperation,
-  data: Request,
-  db: DbParam,
-) -> Result<HttpResponse, Error>
+fn perform<Request, Response>(data: Request, db: DbParam) -> Result<HttpResponse, Error>
 where
   Response: Serialize,
   Oper<Request>: Perform<Response>,
@@ -41,20 +181,16 @@ where
     Ok(c) => c,
     Err(e) => return Err(format_err!("{}", e)),
   };
-  let oper: Oper<Request> = Oper::new(op, data);
+  let oper: Oper<Request> = Oper::new(data);
   let response = oper.perform(&conn);
   Ok(HttpResponse::Ok().json(response?))
 }
 
-fn route<Data, Response>(
-  op: UserOperation,
-) -> Box<(dyn Fn(web::Query<Data>, DbParam) -> Result<HttpResponse, Error> + 'static)>
+async fn route<Data, Response>(data: web::Query<Data>, db: DbParam) -> Result<HttpResponse, Error>
 where
   Data: Serialize,
   Response: Serialize,
   Oper<Data>: Perform<Response>,
 {
-  // TODO: want an implementation like this, where useroperation is passed without explicitly passing the other params
-  //       maybe with a higher order functions? (but that would probably have worse performance)
-  Box::new(|data, db| perform::<Data, Response>(op, data.0, db))
+  perform::<Data, Response>(data.0, db)
 }
index 74f47ad347dafef1f192a5ef058f084e1f99956e..1be3a8e0e899a177d16dadc766ad614a5cc03db6 100644 (file)
@@ -1 +1,44 @@
 pub mod server;
+
+#[derive(EnumString, ToString, Debug)]
+pub enum UserOperation {
+  Login,
+  Register,
+  CreateCommunity,
+  CreatePost,
+  ListCommunities,
+  ListCategories,
+  GetPost,
+  GetCommunity,
+  CreateComment,
+  EditComment,
+  SaveComment,
+  CreateCommentLike,
+  GetPosts,
+  CreatePostLike,
+  EditPost,
+  SavePost,
+  EditCommunity,
+  FollowCommunity,
+  GetFollowedCommunities,
+  GetUserDetails,
+  GetReplies,
+  GetUserMentions,
+  EditUserMention,
+  GetModlog,
+  BanFromCommunity,
+  AddModToCommunity,
+  CreateSite,
+  EditSite,
+  GetSite,
+  AddAdmin,
+  BanUser,
+  Search,
+  MarkAllAsRead,
+  SaveUserSettings,
+  TransferCommunity,
+  TransferSite,
+  DeleteAccount,
+  PasswordReset,
+  PasswordChange,
+}
index 957c5f643296e64c8084fee161485e9dd5ce1153..0386ba4e1cfbe8eebe1d6743e2372d0e1e639875 100644 (file)
@@ -19,6 +19,7 @@ use crate::api::post::*;
 use crate::api::site::*;
 use crate::api::user::*;
 use crate::api::*;
+use crate::websocket::UserOperation;
 use crate::Settings;
 
 /// Chat server sends this messages to session
@@ -201,7 +202,6 @@ impl ChatServer {
           );
           Err(
             APIError {
-              op: "Rate Limit".to_string(),
               message: format!("Too many requests. {} per {} seconds", rate, per),
             }
             .into(),
@@ -295,11 +295,25 @@ impl Handler<StandardMessage> for ChatServer {
   }
 }
 
+fn to_json_string<T>(op: UserOperation, data: T) -> Result<String, Error>
+where
+  T: Serialize,
+{
+  dbg!(&op);
+  let mut json = serde_json::to_value(&data)?;
+  match json.as_object_mut() {
+    Some(j) => j.insert("op".to_string(), serde_json::to_value(op.to_string())?),
+    None => return Err(format_err!("")),
+  };
+  // TODO: it seems like this is never called?
+  let x = serde_json::to_string(&json)?;
+  Ok(x)
+}
+
 fn parse_json_message(chat: &mut ChatServer, msg: StandardMessage) -> Result<String, Error> {
   let json: Value = serde_json::from_str(&msg.msg)?;
   let data = &json["data"].to_string();
   let op = &json["op"].as_str().ok_or(APIError {
-    op: "Unknown op type".to_string(),
     message: "Unknown op type".to_string(),
   })?;
 
@@ -310,12 +324,12 @@ fn parse_json_message(chat: &mut ChatServer, msg: StandardMessage) -> Result<Str
   match user_operation {
     UserOperation::Login => {
       let login: Login = serde_json::from_str(data)?;
-      let res = Oper::new(user_operation, login).perform(&conn)?;
-      Ok(serde_json::to_string(&res)?)
+      let res = Oper::new(login).perform(&conn)?;
+      to_json_string(user_operation, &res)
     }
     UserOperation::Register => {
       let register: Register = serde_json::from_str(data)?;
-      let res = Oper::new(user_operation, register).perform(&conn);
+      let res = Oper::new(register).perform(&conn);
       if res.is_ok() {
         chat.check_rate_limit_register(msg.id)?;
       }
@@ -323,84 +337,84 @@ fn parse_json_message(chat: &mut ChatServer, msg: StandardMessage) -> Result<Str
     }
     UserOperation::GetUserDetails => {
       let get_user_details: GetUserDetails = serde_json::from_str(data)?;
-      let res = Oper::new(user_operation, get_user_details).perform(&conn)?;
-      Ok(serde_json::to_string(&res)?)
+      let res = Oper::new(get_user_details).perform(&conn)?;
+      to_json_string(user_operation, &res)
     }
     UserOperation::SaveUserSettings => {
       let save_user_settings: SaveUserSettings = serde_json::from_str(data)?;
-      let res = Oper::new(user_operation, save_user_settings).perform(&conn)?;
-      Ok(serde_json::to_string(&res)?)
+      let res = Oper::new(save_user_settings).perform(&conn)?;
+      to_json_string(user_operation, &res)
     }
     UserOperation::AddAdmin => {
       let add_admin: AddAdmin = serde_json::from_str(data)?;
-      let res = Oper::new(user_operation, add_admin).perform(&conn)?;
-      Ok(serde_json::to_string(&res)?)
+      let res = Oper::new(add_admin).perform(&conn)?;
+      to_json_string(user_operation, &res)
     }
     UserOperation::BanUser => {
       let ban_user: BanUser = serde_json::from_str(data)?;
-      let res = Oper::new(user_operation, ban_user).perform(&conn)?;
-      Ok(serde_json::to_string(&res)?)
+      let res = Oper::new(ban_user).perform(&conn)?;
+      to_json_string(user_operation, &res)
     }
     UserOperation::GetReplies => {
       let get_replies: GetReplies = serde_json::from_str(data)?;
-      let res = Oper::new(user_operation, get_replies).perform(&conn)?;
-      Ok(serde_json::to_string(&res)?)
+      let res = Oper::new(get_replies).perform(&conn)?;
+      to_json_string(user_operation, &res)
     }
     UserOperation::GetUserMentions => {
       let get_user_mentions: GetUserMentions = serde_json::from_str(data)?;
-      let res = Oper::new(user_operation, get_user_mentions).perform(&conn)?;
-      Ok(serde_json::to_string(&res)?)
+      let res = Oper::new(get_user_mentions).perform(&conn)?;
+      to_json_string(user_operation, &res)
     }
     UserOperation::EditUserMention => {
       let edit_user_mention: EditUserMention = serde_json::from_str(data)?;
-      let res = Oper::new(user_operation, edit_user_mention).perform(&conn)?;
-      Ok(serde_json::to_string(&res)?)
+      let res = Oper::new(edit_user_mention).perform(&conn)?;
+      to_json_string(user_operation, &res)
     }
     UserOperation::MarkAllAsRead => {
       let mark_all_as_read: MarkAllAsRead = serde_json::from_str(data)?;
-      let res = Oper::new(user_operation, mark_all_as_read).perform(&conn)?;
-      Ok(serde_json::to_string(&res)?)
+      let res = Oper::new(mark_all_as_read).perform(&conn)?;
+      to_json_string(user_operation, &res)
     }
     UserOperation::GetCommunity => {
       let get_community: GetCommunity = serde_json::from_str(data)?;
-      let res = Oper::new(user_operation, get_community).perform(&conn)?;
-      Ok(serde_json::to_string(&res)?)
+      let res = Oper::new(get_community).perform(&conn)?;
+      to_json_string(user_operation, &res)
     }
     UserOperation::ListCommunities => {
       let list_communities: ListCommunities = serde_json::from_str(data)?;
-      let res = Oper::new(user_operation, list_communities).perform(&conn)?;
-      Ok(serde_json::to_string(&res)?)
+      let res = Oper::new(list_communities).perform(&conn)?;
+      to_json_string(user_operation, &res)
     }
     UserOperation::CreateCommunity => {
       chat.check_rate_limit_register(msg.id)?;
       let create_community: CreateCommunity = serde_json::from_str(data)?;
-      let res = Oper::new(user_operation, create_community).perform(&conn)?;
-      Ok(serde_json::to_string(&res)?)
+      let res = Oper::new(create_community).perform(&conn)?;
+      to_json_string(user_operation, &res)
     }
     UserOperation::EditCommunity => {
       let edit_community: EditCommunity = serde_json::from_str(data)?;
-      let res = Oper::new(user_operation, edit_community).perform(&conn)?;
+      let res = Oper::new(edit_community).perform(&conn)?;
       let mut community_sent: CommunityResponse = res.clone();
       community_sent.community.user_id = None;
       community_sent.community.subscribed = None;
       let community_sent_str = serde_json::to_string(&community_sent)?;
       chat.send_community_message(community_sent.community.id, &community_sent_str, msg.id)?;
-      Ok(serde_json::to_string(&res)?)
+      to_json_string(user_operation, &res)
     }
     UserOperation::FollowCommunity => {
       let follow_community: FollowCommunity = serde_json::from_str(data)?;
-      let res = Oper::new(user_operation, follow_community).perform(&conn)?;
-      Ok(serde_json::to_string(&res)?)
+      let res = Oper::new(follow_community).perform(&conn)?;
+      to_json_string(user_operation, &res)
     }
     UserOperation::GetFollowedCommunities => {
       let followed_communities: GetFollowedCommunities = serde_json::from_str(data)?;
-      let res = Oper::new(user_operation, followed_communities).perform(&conn)?;
-      Ok(serde_json::to_string(&res)?)
+      let res = Oper::new(followed_communities).perform(&conn)?;
+      to_json_string(user_operation, &res)
     }
     UserOperation::BanFromCommunity => {
       let ban_from_community: BanFromCommunity = serde_json::from_str(data)?;
       let community_id = ban_from_community.community_id;
-      let res = Oper::new(user_operation, ban_from_community).perform(&conn)?;
+      let res = Oper::new(ban_from_community).perform(&conn)?;
       let res_str = serde_json::to_string(&res)?;
       chat.send_community_message(community_id, &res_str, msg.id)?;
       Ok(res_str)
@@ -408,144 +422,144 @@ fn parse_json_message(chat: &mut ChatServer, msg: StandardMessage) -> Result<Str
     UserOperation::AddModToCommunity => {
       let mod_add_to_community: AddModToCommunity = serde_json::from_str(data)?;
       let community_id = mod_add_to_community.community_id;
-      let res = Oper::new(user_operation, mod_add_to_community).perform(&conn)?;
+      let res = Oper::new(mod_add_to_community).perform(&conn)?;
       let res_str = serde_json::to_string(&res)?;
       chat.send_community_message(community_id, &res_str, msg.id)?;
       Ok(res_str)
     }
     UserOperation::ListCategories => {
       let list_categories: ListCategories = ListCategories;
-      let res = Oper::new(user_operation, list_categories).perform(&conn)?;
-      Ok(serde_json::to_string(&res)?)
+      let res = Oper::new(list_categories).perform(&conn)?;
+      to_json_string(user_operation, &res)
     }
     UserOperation::CreatePost => {
       chat.check_rate_limit_post(msg.id)?;
       let create_post: CreatePost = serde_json::from_str(data)?;
-      let res = Oper::new(user_operation, create_post).perform(&conn)?;
-      Ok(serde_json::to_string(&res)?)
+      let res = Oper::new(create_post).perform(&conn)?;
+      to_json_string(user_operation, &res)
     }
     UserOperation::GetPost => {
       let get_post: GetPost = serde_json::from_str(data)?;
       chat.join_room(get_post.id, msg.id);
-      let res = Oper::new(user_operation, get_post).perform(&conn)?;
-      Ok(serde_json::to_string(&res)?)
+      let res = Oper::new(get_post).perform(&conn)?;
+      to_json_string(user_operation, &res)
     }
     UserOperation::GetPosts => {
       let get_posts: GetPosts = serde_json::from_str(data)?;
-      let res = Oper::new(user_operation, get_posts).perform(&conn)?;
-      Ok(serde_json::to_string(&res)?)
+      let res = Oper::new(get_posts).perform(&conn)?;
+      to_json_string(user_operation, &res)
     }
     UserOperation::CreatePostLike => {
       chat.check_rate_limit_message(msg.id)?;
       let create_post_like: CreatePostLike = serde_json::from_str(data)?;
-      let res = Oper::new(user_operation, create_post_like).perform(&conn)?;
-      Ok(serde_json::to_string(&res)?)
+      let res = Oper::new(create_post_like).perform(&conn)?;
+      to_json_string(user_operation, &res)
     }
     UserOperation::EditPost => {
       let edit_post: EditPost = serde_json::from_str(data)?;
-      let res = Oper::new(user_operation, edit_post).perform(&conn)?;
+      let res = Oper::new(edit_post).perform(&conn)?;
       let mut post_sent = res.clone();
       post_sent.post.my_vote = None;
       let post_sent_str = serde_json::to_string(&post_sent)?;
       chat.send_room_message(post_sent.post.id, &post_sent_str, msg.id);
-      Ok(serde_json::to_string(&res)?)
+      to_json_string(user_operation, &res)
     }
     UserOperation::SavePost => {
       let save_post: SavePost = serde_json::from_str(data)?;
-      let res = Oper::new(user_operation, save_post).perform(&conn)?;
-      Ok(serde_json::to_string(&res)?)
+      let res = Oper::new(save_post).perform(&conn)?;
+      to_json_string(user_operation, &res)
     }
     UserOperation::CreateComment => {
       chat.check_rate_limit_message(msg.id)?;
       let create_comment: CreateComment = serde_json::from_str(data)?;
       let post_id = create_comment.post_id;
-      let res = Oper::new(user_operation, create_comment).perform(&conn)?;
+      let res = Oper::new(create_comment).perform(&conn)?;
       let mut comment_sent = res.clone();
       comment_sent.comment.my_vote = None;
       comment_sent.comment.user_id = None;
       let comment_sent_str = serde_json::to_string(&comment_sent)?;
       chat.send_room_message(post_id, &comment_sent_str, msg.id);
-      Ok(serde_json::to_string(&res)?)
+      to_json_string(user_operation, &res)
     }
     UserOperation::EditComment => {
       let edit_comment: EditComment = serde_json::from_str(data)?;
       let post_id = edit_comment.post_id;
-      let res = Oper::new(user_operation, edit_comment).perform(&conn)?;
+      let res = Oper::new(edit_comment).perform(&conn)?;
       let mut comment_sent = res.clone();
       comment_sent.comment.my_vote = None;
       comment_sent.comment.user_id = None;
       let comment_sent_str = serde_json::to_string(&comment_sent)?;
       chat.send_room_message(post_id, &comment_sent_str, msg.id);
-      Ok(serde_json::to_string(&res)?)
+      to_json_string(user_operation, &res)
     }
     UserOperation::SaveComment => {
       let save_comment: SaveComment = serde_json::from_str(data)?;
-      let res = Oper::new(user_operation, save_comment).perform(&conn)?;
-      Ok(serde_json::to_string(&res)?)
+      let res = Oper::new(save_comment).perform(&conn)?;
+      to_json_string(user_operation, &res)
     }
     UserOperation::CreateCommentLike => {
       chat.check_rate_limit_message(msg.id)?;
       let create_comment_like: CreateCommentLike = serde_json::from_str(data)?;
       let post_id = create_comment_like.post_id;
-      let res = Oper::new(user_operation, create_comment_like).perform(&conn)?;
+      let res = Oper::new(create_comment_like).perform(&conn)?;
       let mut comment_sent = res.clone();
       comment_sent.comment.my_vote = None;
       comment_sent.comment.user_id = None;
       let comment_sent_str = serde_json::to_string(&comment_sent)?;
       chat.send_room_message(post_id, &comment_sent_str, msg.id);
-      Ok(serde_json::to_string(&res)?)
+      to_json_string(user_operation, &res)
     }
     UserOperation::GetModlog => {
       let get_modlog: GetModlog = serde_json::from_str(data)?;
-      let res = Oper::new(user_operation, get_modlog).perform(&conn)?;
-      Ok(serde_json::to_string(&res)?)
+      let res = Oper::new(get_modlog).perform(&conn)?;
+      to_json_string(user_operation, &res)
     }
     UserOperation::CreateSite => {
       let create_site: CreateSite = serde_json::from_str(data)?;
-      let res = Oper::new(user_operation, create_site).perform(&conn)?;
-      Ok(serde_json::to_string(&res)?)
+      let res = Oper::new(create_site).perform(&conn)?;
+      to_json_string(user_operation, &res)
     }
     UserOperation::EditSite => {
       let edit_site: EditSite = serde_json::from_str(data)?;
-      let res = Oper::new(user_operation, edit_site).perform(&conn)?;
-      Ok(serde_json::to_string(&res)?)
+      let res = Oper::new(edit_site).perform(&conn)?;
+      to_json_string(user_operation, &res)
     }
     UserOperation::GetSite => {
       let online: usize = chat.sessions.len();
       let get_site: GetSite = serde_json::from_str(data)?;
-      let mut res = Oper::new(user_operation, get_site).perform(&conn)?;
+      let mut res = Oper::new(get_site).perform(&conn)?;
       res.online = online;
-      Ok(serde_json::to_string(&res)?)
+      to_json_string(user_operation, &res)
     }
     UserOperation::Search => {
       let search: Search = serde_json::from_str(data)?;
-      let res = Oper::new(user_operation, search).perform(&conn)?;
-      Ok(serde_json::to_string(&res)?)
+      let res = Oper::new(search).perform(&conn)?;
+      to_json_string(user_operation, &res)
     }
     UserOperation::TransferCommunity => {
       let transfer_community: TransferCommunity = serde_json::from_str(data)?;
-      let res = Oper::new(user_operation, transfer_community).perform(&conn)?;
-      Ok(serde_json::to_string(&res)?)
+      let res = Oper::new(transfer_community).perform(&conn)?;
+      to_json_string(user_operation, &res)
     }
     UserOperation::TransferSite => {
       let transfer_site: TransferSite = serde_json::from_str(data)?;
-      let res = Oper::new(user_operation, transfer_site).perform(&conn)?;
-      Ok(serde_json::to_string(&res)?)
+      let res = Oper::new(transfer_site).perform(&conn)?;
+      to_json_string(user_operation, &res)
     }
     UserOperation::DeleteAccount => {
       let delete_account: DeleteAccount = serde_json::from_str(data)?;
-      let res = Oper::new(user_operation, delete_account).perform(&conn)?;
-      Ok(serde_json::to_string(&res)?)
+      let res = Oper::new(delete_account).perform(&conn)?;
+      to_json_string(user_operation, &res)
     }
     UserOperation::PasswordReset => {
       let password_reset: PasswordReset = serde_json::from_str(data)?;
-      let res = Oper::new(user_operation, password_reset).perform(&conn)?;
-      Ok(serde_json::to_string(&res)?)
+      let res = Oper::new(password_reset).perform(&conn)?;
+      to_json_string(user_operation, &res)
     }
     UserOperation::PasswordChange => {
       let password_change: PasswordChange = serde_json::from_str(data)?;
-      let res = Oper::new(user_operation, password_change).perform(&conn)?;
-      Ok(serde_json::to_string(&res)?)
+      let res = Oper::new(password_change).perform(&conn)?;
+      to_json_string(user_operation, &res)
     }
   }
 }