From ff026dc3fff207278fbb83c1e6e02856ad5af2a9 Mon Sep 17 00:00:00 2001
From: Dessalines <dessalines@users.noreply.github.com>
Date: Fri, 8 Jul 2022 06:21:33 -0400
Subject: [PATCH] Adding check for requests with no id or name, adding max
 limit. (#2265)

* Adding check for requests with no id or name, adding max limit.

* Consolidating a few functions.

* Fix page min

* Adding more websocket rate limits.

* Add check to GetCommunity

* Use a default message rate limit check.

* Adding a page and limit checker

* Fix clippy

* Fix clippy again

* Adding check for requests with no id or name, adding max limit.

* Consolidating a few functions.

* Fix page min

* Adding more websocket rate limits.

* Add check to GetCommunity

* Use a default message rate limit check.

* Adding a page and limit checker

* Fix clippy

* Fix clippy again

* Fix limit request.

* Move checks to inside limit_and_offset

* Fixing API tests.

* Change NotFound diesel errors to QueryBuilderError
---
 api_tests/src/shared.ts                       |  1 -
 api_tests/src/user.spec.ts                    |  1 -
 .../local_user/notifications/mark_all_read.rs |  2 +-
 crates/api_common/src/utils.rs                | 15 +++++++
 crates/api_crud/src/comment/list.rs           | 10 ++++-
 crates/api_crud/src/community/read.rs         |  4 ++
 crates/api_crud/src/post/list.rs              | 23 +++++------
 crates/api_crud/src/post/read.rs              |  2 +-
 crates/api_crud/src/user/read.rs              |  6 +++
 crates/db_schema/src/impls/post.rs            |  4 +-
 crates/db_schema/src/utils.rs                 | 39 +++++++++++++++++--
 crates/db_views/src/comment_report_view.rs    |  2 +-
 crates/db_views/src/comment_view.rs           | 37 +++++++++++-------
 crates/db_views/src/post_report_view.rs       |  2 +-
 crates/db_views/src/post_view.rs              | 33 ++++++++++------
 crates/db_views/src/private_message_view.rs   |  2 +-
 .../src/registration_application_view.rs      |  2 +-
 crates/db_views_actor/src/community_view.rs   |  2 +-
 .../db_views_actor/src/person_mention_view.rs |  2 +-
 crates/db_views_actor/src/person_view.rs      |  2 +-
 .../src/admin_purge_comment_view.rs           |  2 +-
 .../src/admin_purge_community_view.rs         |  2 +-
 .../src/admin_purge_person_view.rs            |  2 +-
 .../src/admin_purge_post_view.rs              |  2 +-
 .../src/mod_add_community_view.rs             |  2 +-
 crates/db_views_moderator/src/mod_add_view.rs |  2 +-
 .../src/mod_ban_from_community_view.rs        |  2 +-
 crates/db_views_moderator/src/mod_ban_view.rs |  2 +-
 .../src/mod_hide_community_view.rs            |  2 +-
 .../src/mod_lock_post_view.rs                 |  2 +-
 .../src/mod_remove_comment_view.rs            |  2 +-
 .../src/mod_remove_community_view.rs          |  2 +-
 .../src/mod_remove_post_view.rs               |  2 +-
 .../src/mod_sticky_post_view.rs               |  2 +-
 .../src/mod_transfer_community_view.rs        |  2 +-
 crates/websocket/src/chat_server.rs           |  4 +-
 36 files changed, 150 insertions(+), 75 deletions(-)

diff --git a/api_tests/src/shared.ts b/api_tests/src/shared.ts
index 32179eeb2..65effc627 100644
--- a/api_tests/src/shared.ts
+++ b/api_tests/src/shared.ts
@@ -586,7 +586,6 @@ export async function listPrivateMessages(
   let form: GetPrivateMessages = {
     auth: api.auth,
     unread_only: false,
-    limit: 999,
   };
   return api.client.getPrivateMessages(form);
 }
diff --git a/api_tests/src/user.spec.ts b/api_tests/src/user.spec.ts
index 29029ac1e..bce36e2af 100644
--- a/api_tests/src/user.spec.ts
+++ b/api_tests/src/user.spec.ts
@@ -7,7 +7,6 @@ import {
   saveUserSettings,
   getSite,
   createPost,
-  gamma,
   resolveCommunity,
   createComment,
   resolveBetaCommunity,
diff --git a/crates/api/src/local_user/notifications/mark_all_read.rs b/crates/api/src/local_user/notifications/mark_all_read.rs
index 3925e7913..9d79acf79 100644
--- a/crates/api/src/local_user/notifications/mark_all_read.rs
+++ b/crates/api/src/local_user/notifications/mark_all_read.rs
@@ -34,7 +34,7 @@ impl Perform for MarkAllAsRead {
         .recipient_id(person_id)
         .unread_only(true)
         .page(1)
-        .limit(999)
+        .limit(std::i64::MAX)
         .list()
     })
     .await??;
diff --git a/crates/api_common/src/utils.rs b/crates/api_common/src/utils.rs
index e96325cfd..6e82a117c 100644
--- a/crates/api_common/src/utils.rs
+++ b/crates/api_common/src/utils.rs
@@ -15,6 +15,7 @@ use lemmy_db_schema::{
   },
   traits::{Crud, Readable},
   utils::DbPool,
+  ListingType,
 };
 use lemmy_db_views::{
   comment_view::CommentQueryBuilder,
@@ -34,6 +35,7 @@ use lemmy_utils::{
 };
 use reqwest_middleware::ClientWithMiddleware;
 use rosetta_i18n::{Language, LanguageId};
+use std::str::FromStr;
 use tracing::warn;
 
 pub async fn blocking<F, T>(pool: &DbPool, f: F) -> Result<T, LemmyError>
@@ -716,3 +718,16 @@ pub async fn delete_user_account(
 
   Ok(())
 }
+
+pub async fn listing_type_with_site_default(
+  listing_type: Option<ListingType>,
+  pool: &DbPool,
+) -> Result<ListingType, LemmyError> {
+  Ok(match listing_type {
+    Some(l) => l,
+    None => {
+      let site = blocking(pool, Site::read_local_site).await??;
+      ListingType::from_str(&site.default_post_listing_type)?
+    }
+  })
+}
diff --git a/crates/api_crud/src/comment/list.rs b/crates/api_crud/src/comment/list.rs
index 6b949ab6a..87262dce7 100644
--- a/crates/api_crud/src/comment/list.rs
+++ b/crates/api_crud/src/comment/list.rs
@@ -2,7 +2,12 @@ use crate::PerformCrud;
 use actix_web::web::Data;
 use lemmy_api_common::{
   comment::{GetComments, GetCommentsResponse},
-  utils::{blocking, check_private_instance, get_local_user_view_from_jwt_opt},
+  utils::{
+    blocking,
+    check_private_instance,
+    get_local_user_view_from_jwt_opt,
+    listing_type_with_site_default,
+  },
 };
 use lemmy_apub::{fetcher::resolve_actor_identifier, objects::community::ApubCommunity};
 use lemmy_db_schema::{source::community::Community, traits::DeleteableOrRemoveable};
@@ -33,6 +38,8 @@ impl PerformCrud for GetComments {
     let person_id = local_user_view.map(|u| u.person.id);
 
     let community_id = data.community_id;
+    let listing_type = listing_type_with_site_default(data.type_, context.pool()).await?;
+
     let community_actor_id = if let Some(name) = &data.community_name {
       resolve_actor_identifier::<ApubCommunity, Community>(name, context)
         .await
@@ -42,7 +49,6 @@ impl PerformCrud for GetComments {
       None
     };
     let sort = data.sort;
-    let listing_type = data.type_;
     let saved_only = data.saved_only;
     let page = data.page;
     let limit = data.limit;
diff --git a/crates/api_crud/src/community/read.rs b/crates/api_crud/src/community/read.rs
index 8b9c1bdb5..32668b02b 100644
--- a/crates/api_crud/src/community/read.rs
+++ b/crates/api_crud/src/community/read.rs
@@ -31,6 +31,10 @@ impl PerformCrud for GetCommunity {
       get_local_user_view_from_jwt_opt(data.auth.as_ref(), context.pool(), context.secret())
         .await?;
 
+    if data.name.is_none() && data.id.is_none() {
+      return Err(LemmyError::from_message("no_id_given"));
+    }
+
     check_private_instance(&local_user_view, context.pool()).await?;
 
     let person_id = local_user_view.map(|u| u.person.id);
diff --git a/crates/api_crud/src/post/list.rs b/crates/api_crud/src/post/list.rs
index 90806cf20..1af4f55bf 100644
--- a/crates/api_crud/src/post/list.rs
+++ b/crates/api_crud/src/post/list.rs
@@ -2,18 +2,18 @@ use crate::PerformCrud;
 use actix_web::web::Data;
 use lemmy_api_common::{
   post::{GetPosts, GetPostsResponse},
-  utils::{blocking, check_private_instance, get_local_user_view_from_jwt_opt},
+  utils::{
+    blocking,
+    check_private_instance,
+    get_local_user_view_from_jwt_opt,
+    listing_type_with_site_default,
+  },
 };
 use lemmy_apub::{fetcher::resolve_actor_identifier, objects::community::ApubCommunity};
-use lemmy_db_schema::{
-  source::{community::Community, site::Site},
-  traits::DeleteableOrRemoveable,
-  ListingType,
-};
+use lemmy_db_schema::{source::community::Community, traits::DeleteableOrRemoveable};
 use lemmy_db_views::post_view::PostQueryBuilder;
 use lemmy_utils::{error::LemmyError, ConnectionId};
 use lemmy_websocket::LemmyContext;
-use std::str::FromStr;
 
 #[async_trait::async_trait(?Send)]
 impl PerformCrud for GetPosts {
@@ -43,13 +43,8 @@ impl PerformCrud for GetPosts {
       .map(|t| t.local_user.show_read_posts);
 
     let sort = data.sort;
-    let listing_type: ListingType = match data.type_ {
-      Some(l) => l,
-      None => {
-        let site = blocking(context.pool(), Site::read_local_site).await??;
-        ListingType::from_str(&site.default_post_listing_type)?
-      }
-    };
+    let listing_type = listing_type_with_site_default(data.type_, context.pool()).await?;
+
     let page = data.page;
     let limit = data.limit;
     let community_id = data.community_id;
diff --git a/crates/api_crud/src/post/read.rs b/crates/api_crud/src/post/read.rs
index 36a0b290b..801cfbd04 100644
--- a/crates/api_crud/src/post/read.rs
+++ b/crates/api_crud/src/post/read.rs
@@ -50,7 +50,7 @@ impl PerformCrud for GetPost {
         .my_person_id(person_id)
         .show_bot_accounts(show_bot_accounts)
         .post_id(id)
-        .limit(9999)
+        .limit(std::i64::MAX)
         .list()
     })
     .await??;
diff --git a/crates/api_crud/src/user/read.rs b/crates/api_crud/src/user/read.rs
index ecfd45e09..426c44056 100644
--- a/crates/api_crud/src/user/read.rs
+++ b/crates/api_crud/src/user/read.rs
@@ -22,6 +22,12 @@ impl PerformCrud for GetPersonDetails {
     _websocket_id: Option<ConnectionId>,
   ) -> Result<GetPersonDetailsResponse, LemmyError> {
     let data: &GetPersonDetails = self;
+
+    // Check to make sure a person name or an id is given
+    if data.username.is_none() && data.person_id.is_none() {
+      return Err(LemmyError::from_message("no_id_given"));
+    }
+
     let local_user_view =
       get_local_user_view_from_jwt_opt(data.auth.as_ref(), context.pool(), context.secret())
         .await?;
diff --git a/crates/db_schema/src/impls/post.rs b/crates/db_schema/src/impls/post.rs
index 999673416..d616229a2 100644
--- a/crates/db_schema/src/impls/post.rs
+++ b/crates/db_schema/src/impls/post.rs
@@ -11,7 +11,7 @@ use crate::{
     PostSavedForm,
   },
   traits::{Crud, DeleteableOrRemoveable, Likeable, Readable, Saveable},
-  utils::naive_now,
+  utils::{naive_now, FETCH_LIMIT_MAX},
 };
 use diesel::{dsl::*, result::Error, ExpressionMethods, PgConnection, QueryDsl, RunQueryDsl, *};
 use url::Url;
@@ -54,7 +54,7 @@ impl Post {
       .filter(removed.eq(false))
       .then_order_by(published.desc())
       .then_order_by(stickied.desc())
-      .limit(20)
+      .limit(FETCH_LIMIT_MAX)
       .load::<Self>(conn)
   }
 
diff --git a/crates/db_schema/src/utils.rs b/crates/db_schema/src/utils.rs
index c9ccc1700..bd9435e3e 100644
--- a/crates/db_schema/src/utils.rs
+++ b/crates/db_schema/src/utils.rs
@@ -4,6 +4,7 @@ use chrono::NaiveDateTime;
 use diesel::{
   backend::Backend,
   deserialize::FromSql,
+  result::Error::QueryBuilderError,
   serialize::{Output, ToSql},
   sql_types::Text,
   Connection,
@@ -15,6 +16,9 @@ use regex::Regex;
 use std::{env, env::VarError, io::Write};
 use url::Url;
 
+const FETCH_LIMIT_DEFAULT: i64 = 10;
+pub const FETCH_LIMIT_MAX: i64 = 50;
+
 pub type DbPool = diesel::r2d2::Pool<diesel::r2d2::ConnectionManager<diesel::PgConnection>>;
 
 pub fn get_database_url_from_env() -> Result<String, VarError> {
@@ -26,10 +30,39 @@ pub fn fuzzy_search(q: &str) -> String {
   format!("%{}%", replaced)
 }
 
-pub fn limit_and_offset(page: Option<i64>, limit: Option<i64>) -> (i64, i64) {
-  let page = page.unwrap_or(1);
-  let limit = limit.unwrap_or(10);
+pub fn limit_and_offset(
+  page: Option<i64>,
+  limit: Option<i64>,
+) -> Result<(i64, i64), diesel::result::Error> {
+  let page = match page {
+    Some(page) => {
+      if page < 1 {
+        return Err(QueryBuilderError("Page is < 1".into()));
+      } else {
+        page
+      }
+    }
+    None => 1,
+  };
+  let limit = match limit {
+    Some(limit) => {
+      if !(1..=FETCH_LIMIT_MAX).contains(&limit) {
+        return Err(QueryBuilderError(
+          format!("Fetch limit is > {}", FETCH_LIMIT_MAX).into(),
+        ));
+      } else {
+        limit
+      }
+    }
+    None => FETCH_LIMIT_DEFAULT,
+  };
   let offset = limit * (page - 1);
+  Ok((limit, offset))
+}
+
+pub fn limit_and_offset_unlimited(page: Option<i64>, limit: Option<i64>) -> (i64, i64) {
+  let limit = limit.unwrap_or(FETCH_LIMIT_DEFAULT);
+  let offset = limit * (page.unwrap_or(1) - 1);
   (limit, offset)
 }
 
diff --git a/crates/db_views/src/comment_report_view.rs b/crates/db_views/src/comment_report_view.rs
index bca8afdc0..946503efe 100644
--- a/crates/db_views/src/comment_report_view.rs
+++ b/crates/db_views/src/comment_report_view.rs
@@ -256,7 +256,7 @@ impl<'a> CommentReportQueryBuilder<'a> {
       query = query.filter(comment_report::resolved.eq(false));
     }
 
-    let (limit, offset) = limit_and_offset(self.page, self.limit);
+    let (limit, offset) = limit_and_offset(self.page, self.limit)?;
 
     query = query
       .order_by(comment_report::published.desc())
diff --git a/crates/db_views/src/comment_view.rs b/crates/db_views/src/comment_view.rs
index 2852a6ca6..6a665975c 100644
--- a/crates/db_views/src/comment_view.rs
+++ b/crates/db_views/src/comment_view.rs
@@ -1,5 +1,9 @@
 use crate::structs::CommentView;
-use diesel::{dsl::*, result::Error, *};
+use diesel::{
+  dsl::*,
+  result::{Error, Error::QueryBuilderError},
+  *,
+};
 use lemmy_db_schema::{
   aggregates::structs::CommentAggregates,
   newtypes::{CommentId, CommunityId, DbUrl, PersonId, PostId},
@@ -26,7 +30,7 @@ use lemmy_db_schema::{
     post::Post,
   },
   traits::{MaybeOptional, ToSafe, ViewToVec},
-  utils::{functions::hot_rank, fuzzy_search, limit_and_offset},
+  utils::{functions::hot_rank, fuzzy_search, limit_and_offset_unlimited},
   ListingType,
   SortType,
 };
@@ -414,14 +418,6 @@ impl<'a> CommentQueryBuilder<'a> {
       query = query.filter(comment::creator_id.eq(creator_id));
     };
 
-    if let Some(community_id) = self.community_id {
-      query = query.filter(post::community_id.eq(community_id));
-    }
-
-    if let Some(community_actor_id) = self.community_actor_id {
-      query = query.filter(community::actor_id.eq(community_actor_id))
-    }
-
     if let Some(post_id) = self.post_id {
       query = query.filter(comment::post_id.eq(post_id));
     };
@@ -449,9 +445,21 @@ impl<'a> CommentQueryBuilder<'a> {
               .or(community_follower::person_id.eq(person_id_join)),
           )
         }
-        ListingType::Community => {}
-      };
-    }
+        ListingType::Community => {
+          if self.community_actor_id.is_none() && self.community_id.is_none() {
+            return Err(QueryBuilderError("No community actor or id given".into()));
+          } else {
+            if let Some(community_id) = self.community_id {
+              query = query.filter(post::community_id.eq(community_id));
+            }
+
+            if let Some(community_actor_id) = self.community_actor_id {
+              query = query.filter(community::actor_id.eq(community_actor_id))
+            }
+          }
+        }
+      }
+    };
 
     if self.saved_only.unwrap_or(false) {
       query = query.filter(comment_saved::id.is_not_null());
@@ -489,7 +497,8 @@ impl<'a> CommentQueryBuilder<'a> {
       query = query.filter(person_block::person_id.is_null());
     }
 
-    let (limit, offset) = limit_and_offset(self.page, self.limit);
+    // Don't use the regular error-checking one, many more comments must ofter be fetched.
+    let (limit, offset) = limit_and_offset_unlimited(self.page, self.limit);
 
     // Note: deleted and removed comments are done on the front side
     let res = query
diff --git a/crates/db_views/src/post_report_view.rs b/crates/db_views/src/post_report_view.rs
index 9769ec021..64550d214 100644
--- a/crates/db_views/src/post_report_view.rs
+++ b/crates/db_views/src/post_report_view.rs
@@ -241,7 +241,7 @@ impl<'a> PostReportQueryBuilder<'a> {
       query = query.filter(post_report::resolved.eq(false));
     }
 
-    let (limit, offset) = limit_and_offset(self.page, self.limit);
+    let (limit, offset) = limit_and_offset(self.page, self.limit)?;
 
     query = query
       .order_by(post_report::published.desc())
diff --git a/crates/db_views/src/post_view.rs b/crates/db_views/src/post_view.rs
index 8b02c91a3..65b177cb1 100644
--- a/crates/db_views/src/post_view.rs
+++ b/crates/db_views/src/post_view.rs
@@ -1,5 +1,10 @@
 use crate::structs::PostView;
-use diesel::{dsl::*, pg::Pg, result::Error, *};
+use diesel::{
+  dsl::*,
+  pg::Pg,
+  result::{Error, Error::QueryBuilderError},
+  *,
+};
 use lemmy_db_schema::{
   aggregates::structs::PostAggregates,
   newtypes::{CommunityId, DbUrl, PersonId, PostId},
@@ -358,21 +363,25 @@ impl<'a> PostQueryBuilder<'a> {
           )
         }
         ListingType::Community => {
-          if let Some(community_id) = self.community_id {
-            query = query
-              .filter(post::community_id.eq(community_id))
-              .then_order_by(post_aggregates::stickied.desc());
+          if self.community_actor_id.is_none() && self.community_id.is_none() {
+            return Err(QueryBuilderError("No community actor or id given".into()));
+          } else {
+            if let Some(community_id) = self.community_id {
+              query = query
+                .filter(post::community_id.eq(community_id))
+                .then_order_by(post_aggregates::stickied.desc());
+            }
+
+            if let Some(community_actor_id) = self.community_actor_id {
+              query = query
+                .filter(community::actor_id.eq(community_actor_id))
+                .then_order_by(post_aggregates::stickied.desc());
+            }
           }
         }
       }
     }
 
-    if let Some(community_actor_id) = self.community_actor_id {
-      query = query
-        .filter(community::actor_id.eq(community_actor_id))
-        .then_order_by(post_aggregates::stickied.desc());
-    }
-
     if let Some(url_search) = self.url_search {
       query = query.filter(post::url.eq(url_search));
     }
@@ -455,7 +464,7 @@ impl<'a> PostQueryBuilder<'a> {
         .then_order_by(post_aggregates::published.desc()),
     };
 
-    let (limit, offset) = limit_and_offset(self.page, self.limit);
+    let (limit, offset) = limit_and_offset(self.page, self.limit)?;
 
     query = query
       .limit(limit)
diff --git a/crates/db_views/src/private_message_view.rs b/crates/db_views/src/private_message_view.rs
index fdf5b8e14..185bd3022 100644
--- a/crates/db_views/src/private_message_view.rs
+++ b/crates/db_views/src/private_message_view.rs
@@ -107,7 +107,7 @@ impl<'a> PrivateMessageQueryBuilder<'a> {
       )
     }
 
-    let (limit, offset) = limit_and_offset(self.page, self.limit);
+    let (limit, offset) = limit_and_offset(self.page, self.limit)?;
 
     query = query
       .filter(private_message::deleted.eq(false))
diff --git a/crates/db_views/src/registration_application_view.rs b/crates/db_views/src/registration_application_view.rs
index 00c79323b..2e3724d14 100644
--- a/crates/db_views/src/registration_application_view.rs
+++ b/crates/db_views/src/registration_application_view.rs
@@ -134,7 +134,7 @@ impl<'a> RegistrationApplicationQueryBuilder<'a> {
       query = query.filter(local_user::email_verified.eq(true))
     }
 
-    let (limit, offset) = limit_and_offset(self.page, self.limit);
+    let (limit, offset) = limit_and_offset(self.page, self.limit)?;
 
     query = query
       .limit(limit)
diff --git a/crates/db_views_actor/src/community_view.rs b/crates/db_views_actor/src/community_view.rs
index 99546992b..21a717258 100644
--- a/crates/db_views_actor/src/community_view.rs
+++ b/crates/db_views_actor/src/community_view.rs
@@ -242,7 +242,7 @@ impl<'a> CommunityQueryBuilder<'a> {
       }
     }
 
-    let (limit, offset) = limit_and_offset(self.page, self.limit);
+    let (limit, offset) = limit_and_offset(self.page, self.limit)?;
     let res = query
       .limit(limit)
       .offset(offset)
diff --git a/crates/db_views_actor/src/person_mention_view.rs b/crates/db_views_actor/src/person_mention_view.rs
index d65c165c3..8b92c2f9a 100644
--- a/crates/db_views_actor/src/person_mention_view.rs
+++ b/crates/db_views_actor/src/person_mention_view.rs
@@ -311,7 +311,7 @@ impl<'a> PersonMentionQueryBuilder<'a> {
         .order_by(comment_aggregates::score.desc()),
     };
 
-    let (limit, offset) = limit_and_offset(self.page, self.limit);
+    let (limit, offset) = limit_and_offset(self.page, self.limit)?;
 
     let res = query
       .limit(limit)
diff --git a/crates/db_views_actor/src/person_view.rs b/crates/db_views_actor/src/person_view.rs
index 83886a190..307f02484 100644
--- a/crates/db_views_actor/src/person_view.rs
+++ b/crates/db_views_actor/src/person_view.rs
@@ -124,7 +124,7 @@ impl<'a> PersonQueryBuilder<'a> {
         .order_by(person_aggregates::comment_score.desc()),
     };
 
-    let (limit, offset) = limit_and_offset(self.page, self.limit);
+    let (limit, offset) = limit_and_offset(self.page, self.limit)?;
     query = query.limit(limit).offset(offset);
 
     let res = query.load::<PersonViewSafeTuple>(self.conn)?;
diff --git a/crates/db_views_moderator/src/admin_purge_comment_view.rs b/crates/db_views_moderator/src/admin_purge_comment_view.rs
index b8c8f7456..c2928de64 100644
--- a/crates/db_views_moderator/src/admin_purge_comment_view.rs
+++ b/crates/db_views_moderator/src/admin_purge_comment_view.rs
@@ -35,7 +35,7 @@ impl AdminPurgeCommentView {
       query = query.filter(admin_purge_comment::admin_person_id.eq(admin_person_id));
     };
 
-    let (limit, offset) = limit_and_offset(page, limit);
+    let (limit, offset) = limit_and_offset(page, limit)?;
 
     let res = query
       .limit(limit)
diff --git a/crates/db_views_moderator/src/admin_purge_community_view.rs b/crates/db_views_moderator/src/admin_purge_community_view.rs
index 0c40a3963..20903efcc 100644
--- a/crates/db_views_moderator/src/admin_purge_community_view.rs
+++ b/crates/db_views_moderator/src/admin_purge_community_view.rs
@@ -32,7 +32,7 @@ impl AdminPurgeCommunityView {
       query = query.filter(admin_purge_community::admin_person_id.eq(admin_person_id));
     };
 
-    let (limit, offset) = limit_and_offset(page, limit);
+    let (limit, offset) = limit_and_offset(page, limit)?;
 
     let res = query
       .limit(limit)
diff --git a/crates/db_views_moderator/src/admin_purge_person_view.rs b/crates/db_views_moderator/src/admin_purge_person_view.rs
index 9828e432c..e6ab093b9 100644
--- a/crates/db_views_moderator/src/admin_purge_person_view.rs
+++ b/crates/db_views_moderator/src/admin_purge_person_view.rs
@@ -32,7 +32,7 @@ impl AdminPurgePersonView {
       query = query.filter(admin_purge_person::admin_person_id.eq(admin_person_id));
     };
 
-    let (limit, offset) = limit_and_offset(page, limit);
+    let (limit, offset) = limit_and_offset(page, limit)?;
 
     let res = query
       .limit(limit)
diff --git a/crates/db_views_moderator/src/admin_purge_post_view.rs b/crates/db_views_moderator/src/admin_purge_post_view.rs
index 6665e4675..981d51b3d 100644
--- a/crates/db_views_moderator/src/admin_purge_post_view.rs
+++ b/crates/db_views_moderator/src/admin_purge_post_view.rs
@@ -35,7 +35,7 @@ impl AdminPurgePostView {
       query = query.filter(admin_purge_post::admin_person_id.eq(admin_person_id));
     };
 
-    let (limit, offset) = limit_and_offset(page, limit);
+    let (limit, offset) = limit_and_offset(page, limit)?;
 
     let res = query
       .limit(limit)
diff --git a/crates/db_views_moderator/src/mod_add_community_view.rs b/crates/db_views_moderator/src/mod_add_community_view.rs
index 55bb9d99b..32fe7c777 100644
--- a/crates/db_views_moderator/src/mod_add_community_view.rs
+++ b/crates/db_views_moderator/src/mod_add_community_view.rs
@@ -44,7 +44,7 @@ impl ModAddCommunityView {
       query = query.filter(mod_add_community::community_id.eq(community_id));
     };
 
-    let (limit, offset) = limit_and_offset(page, limit);
+    let (limit, offset) = limit_and_offset(page, limit)?;
 
     let res = query
       .limit(limit)
diff --git a/crates/db_views_moderator/src/mod_add_view.rs b/crates/db_views_moderator/src/mod_add_view.rs
index 5b48d0066..874615a8e 100644
--- a/crates/db_views_moderator/src/mod_add_view.rs
+++ b/crates/db_views_moderator/src/mod_add_view.rs
@@ -34,7 +34,7 @@ impl ModAddView {
       query = query.filter(mod_add::mod_person_id.eq(mod_person_id));
     };
 
-    let (limit, offset) = limit_and_offset(page, limit);
+    let (limit, offset) = limit_and_offset(page, limit)?;
 
     let res = query
       .limit(limit)
diff --git a/crates/db_views_moderator/src/mod_ban_from_community_view.rs b/crates/db_views_moderator/src/mod_ban_from_community_view.rs
index 9e44e4797..f5ce3fa90 100644
--- a/crates/db_views_moderator/src/mod_ban_from_community_view.rs
+++ b/crates/db_views_moderator/src/mod_ban_from_community_view.rs
@@ -49,7 +49,7 @@ impl ModBanFromCommunityView {
       query = query.filter(mod_ban_from_community::community_id.eq(community_id));
     };
 
-    let (limit, offset) = limit_and_offset(page, limit);
+    let (limit, offset) = limit_and_offset(page, limit)?;
 
     let res = query
       .limit(limit)
diff --git a/crates/db_views_moderator/src/mod_ban_view.rs b/crates/db_views_moderator/src/mod_ban_view.rs
index a36adaad0..06e610deb 100644
--- a/crates/db_views_moderator/src/mod_ban_view.rs
+++ b/crates/db_views_moderator/src/mod_ban_view.rs
@@ -34,7 +34,7 @@ impl ModBanView {
       query = query.filter(mod_ban::mod_person_id.eq(mod_person_id));
     };
 
-    let (limit, offset) = limit_and_offset(page, limit);
+    let (limit, offset) = limit_and_offset(page, limit)?;
 
     let res = query
       .limit(limit)
diff --git a/crates/db_views_moderator/src/mod_hide_community_view.rs b/crates/db_views_moderator/src/mod_hide_community_view.rs
index a83805622..ce0a3e73f 100644
--- a/crates/db_views_moderator/src/mod_hide_community_view.rs
+++ b/crates/db_views_moderator/src/mod_hide_community_view.rs
@@ -41,7 +41,7 @@ impl ModHideCommunityView {
       query = query.filter(mod_hide_community::mod_person_id.eq(admin_id));
     };
 
-    let (limit, offset) = limit_and_offset(page, limit);
+    let (limit, offset) = limit_and_offset(page, limit)?;
 
     let res = query
       .limit(limit)
diff --git a/crates/db_views_moderator/src/mod_lock_post_view.rs b/crates/db_views_moderator/src/mod_lock_post_view.rs
index e9ec5f667..32ec5732b 100644
--- a/crates/db_views_moderator/src/mod_lock_post_view.rs
+++ b/crates/db_views_moderator/src/mod_lock_post_view.rs
@@ -43,7 +43,7 @@ impl ModLockPostView {
       query = query.filter(mod_lock_post::mod_person_id.eq(mod_person_id));
     };
 
-    let (limit, offset) = limit_and_offset(page, limit);
+    let (limit, offset) = limit_and_offset(page, limit)?;
 
     let res = query
       .limit(limit)
diff --git a/crates/db_views_moderator/src/mod_remove_comment_view.rs b/crates/db_views_moderator/src/mod_remove_comment_view.rs
index b2b14f220..a3c7e6473 100644
--- a/crates/db_views_moderator/src/mod_remove_comment_view.rs
+++ b/crates/db_views_moderator/src/mod_remove_comment_view.rs
@@ -55,7 +55,7 @@ impl ModRemoveCommentView {
       query = query.filter(mod_remove_comment::mod_person_id.eq(mod_person_id));
     };
 
-    let (limit, offset) = limit_and_offset(page, limit);
+    let (limit, offset) = limit_and_offset(page, limit)?;
 
     let res = query
       .limit(limit)
diff --git a/crates/db_views_moderator/src/mod_remove_community_view.rs b/crates/db_views_moderator/src/mod_remove_community_view.rs
index 29aad7f92..91fcf511c 100644
--- a/crates/db_views_moderator/src/mod_remove_community_view.rs
+++ b/crates/db_views_moderator/src/mod_remove_community_view.rs
@@ -35,7 +35,7 @@ impl ModRemoveCommunityView {
       query = query.filter(mod_remove_community::mod_person_id.eq(mod_person_id));
     };
 
-    let (limit, offset) = limit_and_offset(page, limit);
+    let (limit, offset) = limit_and_offset(page, limit)?;
 
     let res = query
       .limit(limit)
diff --git a/crates/db_views_moderator/src/mod_remove_post_view.rs b/crates/db_views_moderator/src/mod_remove_post_view.rs
index 849b56391..0368a24b0 100644
--- a/crates/db_views_moderator/src/mod_remove_post_view.rs
+++ b/crates/db_views_moderator/src/mod_remove_post_view.rs
@@ -43,7 +43,7 @@ impl ModRemovePostView {
       query = query.filter(mod_remove_post::mod_person_id.eq(mod_person_id));
     };
 
-    let (limit, offset) = limit_and_offset(page, limit);
+    let (limit, offset) = limit_and_offset(page, limit)?;
 
     let res = query
       .limit(limit)
diff --git a/crates/db_views_moderator/src/mod_sticky_post_view.rs b/crates/db_views_moderator/src/mod_sticky_post_view.rs
index 8b2383ee5..cd0b59aba 100644
--- a/crates/db_views_moderator/src/mod_sticky_post_view.rs
+++ b/crates/db_views_moderator/src/mod_sticky_post_view.rs
@@ -43,7 +43,7 @@ impl ModStickyPostView {
       query = query.filter(mod_sticky_post::mod_person_id.eq(mod_person_id));
     };
 
-    let (limit, offset) = limit_and_offset(page, limit);
+    let (limit, offset) = limit_and_offset(page, limit)?;
 
     let res = query
       .limit(limit)
diff --git a/crates/db_views_moderator/src/mod_transfer_community_view.rs b/crates/db_views_moderator/src/mod_transfer_community_view.rs
index c944a9a10..6e0df7336 100644
--- a/crates/db_views_moderator/src/mod_transfer_community_view.rs
+++ b/crates/db_views_moderator/src/mod_transfer_community_view.rs
@@ -49,7 +49,7 @@ impl ModTransferCommunityView {
       query = query.filter(mod_transfer_community::community_id.eq(community_id));
     };
 
-    let (limit, offset) = limit_and_offset(page, limit);
+    let (limit, offset) = limit_and_offset(page, limit)?;
 
     let res = query
       .limit(limit)
diff --git a/crates/websocket/src/chat_server.rs b/crates/websocket/src/chat_server.rs
index 2337cae32..50ce35933 100644
--- a/crates/websocket/src/chat_server.rs
+++ b/crates/websocket/src/chat_server.rs
@@ -479,7 +479,7 @@ impl ChatServer {
           UserOperationCrud::CreatePost => rate_limiter.post().check(ip),
           UserOperationCrud::CreateCommunity => rate_limiter.register().check(ip),
           UserOperationCrud::CreateComment => rate_limiter.comment().check(ip),
-          _ => true,
+          _ => rate_limiter.message().check(ip),
         };
         let fut = (message_handler_crud)(context, msg.id, user_operation_crud, data);
         (passed, fut)
@@ -488,7 +488,7 @@ impl ChatServer {
         let passed = match user_operation {
           UserOperation::GetCaptcha => rate_limiter.post().check(ip),
           UserOperation::Search => rate_limiter.search().check(ip),
-          _ => true,
+          _ => rate_limiter.message().check(ip),
         };
         let fut = (message_handler)(context, msg.id, user_operation, data);
         (passed, fut)
-- 
GitLab