From: Dessalines Date: Fri, 23 Jun 2023 11:02:05 +0000 (-0400) Subject: Revert "feat: re-added captcha checks (#3249)" (#3288) X-Git-Url: http://these/git/%7B%60%24%7BarchiveTodayUrl%7D/static/%7B%24%7B%60data:application/%24%7Bk%5B1%5D.custom_emoji.image_url%7D?a=commitdiff_plain;h=37a47de3a871830ad002ec1f5c4da672ca430518;p=lemmy.git Revert "feat: re-added captcha checks (#3249)" (#3288) This reverts commit 8a086c82405bc8e2c8cb2fbbcceb10418f231d1b. --- diff --git a/Cargo.lock b/Cargo.lock index 08437ecf..cee02f79 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2526,7 +2526,6 @@ dependencies = [ "base64 0.13.1", "bcrypt", "captcha", - "chrono", "lemmy_api_common", "lemmy_db_schema", "lemmy_db_views", @@ -2577,7 +2576,6 @@ dependencies = [ "actix-web", "async-trait", "bcrypt", - "chrono", "lemmy_api_common", "lemmy_db_schema", "lemmy_db_views", diff --git a/crates/api/Cargo.toml b/crates/api/Cargo.toml index ca792809..2488f2c2 100644 --- a/crates/api/Cargo.toml +++ b/crates/api/Cargo.toml @@ -29,7 +29,6 @@ async-trait = { workspace = true } captcha = { workspace = true } anyhow = { workspace = true } tracing = { workspace = true } -chrono = { workspace = true } [dev-dependencies] serial_test = { workspace = true } diff --git a/crates/api/src/lib.rs b/crates/api/src/lib.rs index 615a8a31..9ff1677d 100644 --- a/crates/api/src/lib.rs +++ b/crates/api/src/lib.rs @@ -1,5 +1,4 @@ use actix_web::web::Data; -use captcha::Captcha; use lemmy_api_common::{context::LemmyContext, utils::local_site_to_slur_regex}; use lemmy_db_schema::source::local_site::LocalSite; use lemmy_utils::{error::LemmyError, utils::slurs::check_slurs}; @@ -21,21 +20,6 @@ pub trait Perform { async fn perform(&self, context: &Data) -> Result; } -/// Converts the captcha to a base64 encoded wav audio file -pub(crate) fn captcha_as_wav_base64(captcha: &Captcha) -> String { - let letters = captcha.as_wav(); - - let mut concat_letters: Vec = Vec::new(); - - for letter in letters { - let bytes = letter.unwrap_or_default(); - concat_letters.extend(bytes); - } - - // Convert to base64 - base64::encode(concat_letters) -} - /// Check size of report and remove whitespace pub(crate) fn check_report_reason(reason: &str, local_site: &LocalSite) -> Result<(), LemmyError> { let slur_regex = &local_site_to_slur_regex(local_site); diff --git a/crates/api/src/local_user/get_captcha.rs b/crates/api/src/local_user/get_captcha.rs deleted file mode 100644 index 6dbc3482..00000000 --- a/crates/api/src/local_user/get_captcha.rs +++ /dev/null @@ -1,53 +0,0 @@ -use crate::{captcha_as_wav_base64, Perform}; -use actix_web::web::Data; -use captcha::{gen, Difficulty}; -use chrono::Duration; -use lemmy_api_common::{ - context::LemmyContext, - person::{CaptchaResponse, GetCaptcha, GetCaptchaResponse}, -}; -use lemmy_db_schema::{ - source::{captcha_answer::CaptchaAnswer, local_site::LocalSite}, - utils::naive_now, -}; -use lemmy_utils::error::LemmyError; - -#[async_trait::async_trait(?Send)] -impl Perform for GetCaptcha { - type Response = GetCaptchaResponse; - - #[tracing::instrument(skip(context))] - async fn perform(&self, context: &Data) -> Result { - let local_site = LocalSite::read(context.pool()).await?; - - if !local_site.captcha_enabled { - return Ok(GetCaptchaResponse { ok: None }); - } - - let captcha = gen(match local_site.captcha_difficulty.as_str() { - "easy" => Difficulty::Easy, - "hard" => Difficulty::Hard, - _ => Difficulty::Medium, - }); - - let answer = captcha.chars_as_string(); - - let png = captcha.as_base64().expect("failed to generate captcha"); - - let uuid = uuid::Uuid::new_v4().to_string(); - - let wav = captcha_as_wav_base64(&captcha); - - let captcha: CaptchaAnswer = CaptchaAnswer { - answer, - uuid: uuid.clone(), - expires: naive_now() + Duration::minutes(10), // expires in 10 minutes - }; - // Stores the captcha item in the db - CaptchaAnswer::insert(context.pool(), &captcha).await?; - - Ok(GetCaptchaResponse { - ok: Some(CaptchaResponse { png, wav, uuid }), - }) - } -} diff --git a/crates/api/src/local_user/mod.rs b/crates/api/src/local_user/mod.rs index 3a92beda..9244f825 100644 --- a/crates/api/src/local_user/mod.rs +++ b/crates/api/src/local_user/mod.rs @@ -3,7 +3,6 @@ mod ban_person; mod block; mod change_password; mod change_password_after_reset; -mod get_captcha; mod list_banned; mod login; mod notifications; diff --git a/crates/api_crud/Cargo.toml b/crates/api_crud/Cargo.toml index 21320a3c..1fb1e5a6 100644 --- a/crates/api_crud/Cargo.toml +++ b/crates/api_crud/Cargo.toml @@ -22,4 +22,3 @@ tracing = { workspace = true } url = { workspace = true } async-trait = { workspace = true } webmention = "0.4.0" -chrono = { worspace = true } diff --git a/crates/api_crud/src/user/create.rs b/crates/api_crud/src/user/create.rs index 871a05d6..f5a26f75 100644 --- a/crates/api_crud/src/user/create.rs +++ b/crates/api_crud/src/user/create.rs @@ -1,7 +1,6 @@ use crate::PerformCrud; use activitypub_federation::http_signatures::generate_actor_keypair; use actix_web::web::Data; -use chrono::NaiveDateTime; use lemmy_api_common::{ context::LemmyContext, person::{LoginResponse, Register}, @@ -20,7 +19,6 @@ use lemmy_api_common::{ use lemmy_db_schema::{ aggregates::structs::PersonAggregates, source::{ - captcha_answer::CaptchaAnswer, local_user::{LocalUser, LocalUserInsertForm}, person::{Person, PersonInsertForm}, registration_application::{RegistrationApplication, RegistrationApplicationInsertForm}, @@ -73,22 +71,6 @@ impl PerformCrud for Register { return Err(LemmyError::from_message("passwords_dont_match")); } - if local_site.site_setup && local_site.captcha_enabled { - let check = CaptchaAnswer::check_captcha( - context.pool(), - CaptchaAnswer { - uuid: data.captcha_uuid.clone().unwrap_or_default(), - answer: data.captcha_answer.clone().unwrap_or_default(), - // not used when checking - expires: NaiveDateTime::MIN, - }, - ) - .await?; - if !check { - return Err(LemmyError::from_message("captcha_incorrect")); - } - } - let slur_regex = local_site_to_slur_regex(&local_site); check_slurs(&data.username, &slur_regex)?; check_slurs_opt(&data.answer, &slur_regex)?; diff --git a/crates/db_schema/src/diesel_ltree.patch b/crates/db_schema/src/diesel_ltree.patch index 2607eb68..d7d49f03 100644 --- a/crates/db_schema/src/diesel_ltree.patch +++ b/crates/db_schema/src/diesel_ltree.patch @@ -1,17 +1,28 @@ ---- schema.rs 2023-06-21 22:25:50.252384233 +0100 -+++ "schema copy.rs" 2023-06-21 22:26:50.452378651 +0100 -@@ -6,10 +6,6 @@ - pub struct ListingTypeEnum; +diff --git a/crates/db_schema/src/schema.rs b/crates/db_schema/src/schema.rs +index 255c6422..f2ccf5e2 100644 +--- a/crates/db_schema/src/schema.rs ++++ b/crates/db_schema/src/schema.rs +@@ -2,16 +2,12 @@ + pub mod sql_types { #[derive(diesel::sql_types::SqlType)] + #[diesel(postgres_type(name = "listing_type_enum"))] + pub struct ListingTypeEnum; + +- #[derive(diesel::sql_types::SqlType)] - #[diesel(postgres_type(name = "ltree"))] - pub struct Ltree; - -- #[derive(diesel::sql_types::SqlType)] + #[derive(diesel::sql_types::SqlType)] #[diesel(postgres_type(name = "registration_mode_enum"))] pub struct RegistrationModeEnum; -@@ -78,7 +74,7 @@ + #[derive(diesel::sql_types::SqlType)] + #[diesel(postgres_type(name = "sort_type_enum"))] +@@ -67,13 +63,13 @@ diesel::table! { + when_ -> Timestamp, + } + } diesel::table! { use diesel::sql_types::*; @@ -20,3 +31,6 @@ comment (id) { id -> Int4, + creator_id -> Int4, + post_id -> Int4, + content -> Text, diff --git a/crates/db_schema/src/impls/captcha_answer.rs b/crates/db_schema/src/impls/captcha_answer.rs deleted file mode 100644 index afd18181..00000000 --- a/crates/db_schema/src/impls/captcha_answer.rs +++ /dev/null @@ -1,164 +0,0 @@ -use crate::{ - schema::captcha_answer, - source::captcha_answer::CaptchaAnswer, - utils::{functions::lower, get_conn, naive_now, DbPool}, -}; -use diesel::{ - delete, - dsl::exists, - insert_into, - result::Error, - select, - ExpressionMethods, - QueryDsl, -}; -use diesel_async::RunQueryDsl; - -impl CaptchaAnswer { - pub async fn insert(pool: &DbPool, captcha: &CaptchaAnswer) -> Result { - let conn = &mut get_conn(pool).await?; - - insert_into(captcha_answer::table) - .values(captcha) - .get_result::(conn) - .await - } - - pub async fn check_captcha(pool: &DbPool, to_check: CaptchaAnswer) -> Result { - let conn = &mut get_conn(pool).await?; - - // delete any expired captchas - delete(captcha_answer::table.filter(captcha_answer::expires.lt(&naive_now()))) - .execute(conn) - .await?; - - // fetch requested captcha - let captcha_exists = select(exists( - captcha_answer::dsl::captcha_answer - .filter((captcha_answer::dsl::uuid).eq(to_check.uuid.clone())) - .filter(lower(captcha_answer::dsl::answer).eq(to_check.answer.to_lowercase().clone())), - )) - .get_result::(conn) - .await?; - - // delete checked captcha - delete(captcha_answer::table.filter(captcha_answer::uuid.eq(to_check.uuid.clone()))) - .execute(conn) - .await?; - - Ok(captcha_exists) - } -} - -#[cfg(test)] -mod tests { - use crate::{ - source::captcha_answer::CaptchaAnswer, - utils::{build_db_pool_for_tests, naive_now}, - }; - use chrono::Duration; - use serial_test::serial; - - #[tokio::test] - #[serial] - async fn test_captcha_happy_path() { - let pool = &build_db_pool_for_tests().await; - - let captcha_a_id = "a".to_string(); - - let _ = CaptchaAnswer::insert( - pool, - &CaptchaAnswer { - uuid: captcha_a_id.clone(), - answer: "XYZ".to_string(), - expires: naive_now() + Duration::minutes(10), - }, - ) - .await; - - let result = CaptchaAnswer::check_captcha( - pool, - CaptchaAnswer { - uuid: captcha_a_id.clone(), - answer: "xyz".to_string(), - expires: chrono::NaiveDateTime::MIN, - }, - ) - .await; - - assert!(result.is_ok()); - assert!(result.unwrap()); - } - - #[tokio::test] - #[serial] - async fn test_captcha_repeat_answer_fails() { - let pool = &build_db_pool_for_tests().await; - - let captcha_a_id = "a".to_string(); - - let _ = CaptchaAnswer::insert( - pool, - &CaptchaAnswer { - uuid: captcha_a_id.clone(), - answer: "XYZ".to_string(), - expires: naive_now() + Duration::minutes(10), - }, - ) - .await; - - let result = CaptchaAnswer::check_captcha( - pool, - CaptchaAnswer { - uuid: captcha_a_id.clone(), - answer: "xyz".to_string(), - expires: chrono::NaiveDateTime::MIN, - }, - ) - .await; - - let result_repeat = CaptchaAnswer::check_captcha( - pool, - CaptchaAnswer { - uuid: captcha_a_id.clone(), - answer: "xyz".to_string(), - expires: chrono::NaiveDateTime::MIN, - }, - ) - .await; - - assert!(result_repeat.is_ok()); - assert!(!result_repeat.unwrap()); - } - - #[tokio::test] - #[serial] - async fn test_captcha_expired_fails() { - let pool = &build_db_pool_for_tests().await; - - let expired_id = "already_expired".to_string(); - - let _ = CaptchaAnswer::insert( - pool, - &CaptchaAnswer { - uuid: expired_id.clone(), - answer: "xyz".to_string(), - expires: naive_now() - Duration::seconds(1), - }, - ) - .await; - - let expired_result = CaptchaAnswer::check_captcha( - pool, - CaptchaAnswer { - uuid: expired_id.clone(), - answer: "xyz".to_string(), - expires: chrono::NaiveDateTime::MIN, - }, - ) - .await; - - assert!(expired_result.is_ok()); - assert!(!expired_result.unwrap()); - } -} diff --git a/crates/db_schema/src/impls/mod.rs b/crates/db_schema/src/impls/mod.rs index f13004d0..915d1c8e 100644 --- a/crates/db_schema/src/impls/mod.rs +++ b/crates/db_schema/src/impls/mod.rs @@ -1,6 +1,5 @@ pub mod activity; pub mod actor_language; -pub mod captcha_answer; pub mod comment; pub mod comment_reply; pub mod comment_report; diff --git a/crates/db_schema/src/schema.rs b/crates/db_schema/src/schema.rs index f244ae66..ac4ddc47 100644 --- a/crates/db_schema/src/schema.rs +++ b/crates/db_schema/src/schema.rs @@ -64,14 +64,6 @@ diesel::table! { } } -diesel::table! { - captcha_answer (uuid) { - uuid -> Text, - answer -> Text, - expires -> Timestamp, - } -} - diesel::table! { use diesel::sql_types::{Bool, Int4, Nullable, Text, Timestamp, Varchar}; use diesel_ltree::sql_types::Ltree; @@ -924,7 +916,6 @@ diesel::allow_tables_to_appear_in_same_query!( admin_purge_community, admin_purge_person, admin_purge_post, - captcha_answer, comment, comment_aggregates, comment_like, diff --git a/crates/db_schema/src/source/captcha_answer.rs b/crates/db_schema/src/source/captcha_answer.rs deleted file mode 100644 index 113b7c96..00000000 --- a/crates/db_schema/src/source/captcha_answer.rs +++ /dev/null @@ -1,14 +0,0 @@ -#[cfg(feature = "full")] -use crate::schema::captcha_answer; -use serde::{Deserialize, Serialize}; -use serde_with::skip_serializing_none; - -#[skip_serializing_none] -#[derive(Clone, PartialEq, Eq, Debug, Serialize, Deserialize)] -#[cfg_attr(feature = "full", derive(Queryable, Insertable, AsChangeset))] -#[cfg_attr(feature = "full", diesel(table_name = captcha_answer))] -pub struct CaptchaAnswer { - pub uuid: String, - pub answer: String, - pub expires: chrono::NaiveDateTime, -} diff --git a/crates/db_schema/src/source/mod.rs b/crates/db_schema/src/source/mod.rs index 926e23e7..9aab4b90 100644 --- a/crates/db_schema/src/source/mod.rs +++ b/crates/db_schema/src/source/mod.rs @@ -1,7 +1,6 @@ #[cfg(feature = "full")] pub mod activity; pub mod actor_language; -pub mod captcha_answer; pub mod comment; pub mod comment_reply; pub mod comment_report; diff --git a/migrations/2023-06-21-153242_add_captcha/down.sql b/migrations/2023-06-21-153242_add_captcha/down.sql deleted file mode 100644 index 4e5b8304..00000000 --- a/migrations/2023-06-21-153242_add_captcha/down.sql +++ /dev/null @@ -1 +0,0 @@ -drop table captcha_answer; \ No newline at end of file diff --git a/migrations/2023-06-21-153242_add_captcha/up.sql b/migrations/2023-06-21-153242_add_captcha/up.sql deleted file mode 100644 index 71467be6..00000000 --- a/migrations/2023-06-21-153242_add_captcha/up.sql +++ /dev/null @@ -1,5 +0,0 @@ -create table captcha_answer ( - uuid text not null primary key, - answer text not null, - expires timestamp not null -); diff --git a/src/api_routes_http.rs b/src/api_routes_http.rs index 375630a9..a2abfa69 100644 --- a/src/api_routes_http.rs +++ b/src/api_routes_http.rs @@ -38,7 +38,6 @@ use lemmy_api_common::{ ChangePassword, DeleteAccount, GetBannedPersons, - GetCaptcha, GetPersonDetails, GetPersonMentions, GetReplies, @@ -273,12 +272,6 @@ pub fn config(cfg: &mut web::ServiceConfig, rate_limit: &RateLimitCell) { .wrap(rate_limit.register()) .route(web::post().to(route_post_crud::)), ) - .service( - // Handle captcha separately - web::resource("/user/get_captcha") - .wrap(rate_limit.post()) - .route(web::get().to(route_get::)), - ) // User actions .service( web::scope("/user")