Adding more rust captcha features. Fixes #1248

pull/1535/head
Dessalines 2021-04-01 13:30:24 -04:00
parent fac024b90c
commit 1ba570092e
7 changed files with 18 additions and 68 deletions

View File

@ -1,9 +1,9 @@
use actix_web::{web, web::Data}; use actix_web::{web, web::Data};
use captcha::Captcha;
use lemmy_api_common::{comment::*, community::*, person::*, post::*, site::*, websocket::*}; use lemmy_api_common::{comment::*, community::*, person::*, post::*, site::*, websocket::*};
use lemmy_utils::{ConnectionId, LemmyError}; use lemmy_utils::{ConnectionId, LemmyError};
use lemmy_websocket::{serialize_websocket_message, LemmyContext, UserOperation}; use lemmy_websocket::{serialize_websocket_message, LemmyContext, UserOperation};
use serde::Deserialize; use serde::Deserialize;
use std::{env, process::Command};
mod comment; mod comment;
mod comment_report; mod comment_report;
@ -158,60 +158,23 @@ where
serialize_websocket_message(&op, &res) serialize_websocket_message(&op, &res)
} }
pub(crate) fn captcha_espeak_wav_base64(captcha: &str) -> Result<String, LemmyError> { /// Converts the captcha to a base64 encoded wav audio file
let mut built_text = String::new(); pub(crate) fn captcha_as_wav_base64(captcha: &Captcha) -> String {
let letters = captcha.as_wav();
// Building proper speech text for espeak let mut concat_letters: Vec<u8> = Vec::new();
for mut c in captcha.chars() {
let new_str = if c.is_alphabetic() {
if c.is_lowercase() {
c.make_ascii_uppercase();
format!("lower case {} ... ", c)
} else {
c.make_ascii_uppercase();
format!("capital {} ... ", c)
}
} else {
format!("{} ...", c)
};
built_text.push_str(&new_str); for letter in letters {
let bytes = letter.unwrap_or_default();
concat_letters.extend(bytes);
} }
espeak_wav_base64(&built_text)
}
pub(crate) fn espeak_wav_base64(text: &str) -> Result<String, LemmyError> {
// Make a temp file path
let uuid = uuid::Uuid::new_v4().to_string();
let file_path = format!(
"{}/lemmy_espeak_{}.wav",
env::temp_dir().to_string_lossy(),
&uuid
);
// Write the wav file
Command::new("espeak")
.arg("-w")
.arg(&file_path)
.arg(text)
.status()?;
// Read the wav file bytes
let bytes = std::fs::read(&file_path)?;
// Delete the file
std::fs::remove_file(file_path)?;
// Convert to base64 // Convert to base64
let base64 = base64::encode(bytes); base64::encode(concat_letters)
Ok(base64)
} }
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::captcha_espeak_wav_base64;
use lemmy_api_common::check_validator_time; use lemmy_api_common::check_validator_time;
use lemmy_db_queries::{establish_unpooled_connection, source::local_user::LocalUser_, Crud}; use lemmy_db_queries::{establish_unpooled_connection, source::local_user::LocalUser_, Crud};
use lemmy_db_schema::source::{ use lemmy_db_schema::source::{
@ -253,9 +216,4 @@ mod tests {
let num_deleted = Person::delete(&conn, inserted_person.id).unwrap(); let num_deleted = Person::delete(&conn, inserted_person.id).unwrap();
assert_eq!(1, num_deleted); assert_eq!(1, num_deleted);
} }
#[test]
fn test_espeak() {
assert!(captcha_espeak_wav_base64("WxRt2l").is_ok())
}
} }

View File

@ -1,4 +1,4 @@
use crate::{captcha_espeak_wav_base64, Perform}; use crate::{captcha_as_wav_base64, Perform};
use actix_web::web::Data; use actix_web::web::Data;
use anyhow::Context; use anyhow::Context;
use bcrypt::verify; use bcrypt::verify;
@ -135,13 +135,11 @@ impl Perform for GetCaptcha {
let answer = captcha.chars_as_string(); let answer = captcha.chars_as_string();
let png_byte_array = captcha.as_png().expect("failed to generate captcha"); let png = captcha.as_base64().expect("failed to generate captcha");
let png = base64::encode(png_byte_array);
let uuid = uuid::Uuid::new_v4().to_string(); let uuid = uuid::Uuid::new_v4().to_string();
let wav = captcha_espeak_wav_base64(&answer).ok(); let wav = captcha_as_wav_base64(&captcha);
let captcha_item = CaptchaItem { let captcha_item = CaptchaItem {
answer, answer,

View File

@ -39,8 +39,8 @@ pub struct GetCaptchaResponse {
#[derive(Serialize)] #[derive(Serialize)]
pub struct CaptchaResponse { pub struct CaptchaResponse {
pub png: String, // A Base64 encoded png pub png: String, // A Base64 encoded png
pub wav: Option<String>, // A Base64 encoded wav audio pub wav: String, // A Base64 encoded wav audio
pub uuid: String, pub uuid: String,
} }

View File

@ -49,9 +49,6 @@ FROM alpine:3.12 as lemmy
# Install libpq for postgres # Install libpq for postgres
RUN apk add libpq RUN apk add libpq
# Install Espeak for captchas
RUN apk add espeak
RUN addgroup -g 1000 lemmy RUN addgroup -g 1000 lemmy
RUN adduser -D -s /bin/sh -u 1000 -G lemmy lemmy RUN adduser -D -s /bin/sh -u 1000 -G lemmy lemmy

View File

@ -19,9 +19,9 @@ RUN --mount=type=cache,target=/app/target \
FROM ubuntu:20.10 FROM ubuntu:20.10
# Install libpq for postgres and espeak # Install libpq for postgres
RUN apt-get update -y RUN apt-get update -y
RUN apt-get install -y libpq-dev espeak RUN apt-get install -y libpq-dev
# Copy resources # Copy resources
COPY config/defaults.hjson /config/defaults.hjson COPY config/defaults.hjson /config/defaults.hjson

View File

@ -49,9 +49,6 @@ FROM alpine:3.12 as lemmy
# Install libpq for postgres # Install libpq for postgres
RUN apk add libpq RUN apk add libpq
# Install Espeak for captchas
RUN apk add espeak
RUN addgroup -g 1000 lemmy RUN addgroup -g 1000 lemmy
RUN adduser -D -s /bin/sh -u 1000 -G lemmy lemmy RUN adduser -D -s /bin/sh -u 1000 -G lemmy lemmy

View File

@ -22,9 +22,9 @@ RUN cp ./target/release/lemmy_server /app/lemmy_server
# The Debian runner # The Debian runner
FROM debian:buster-slim as lemmy FROM debian:buster-slim as lemmy
# Install libpq for postgres and espeak for captchas # Install libpq for postgres
RUN apt-get update \ RUN apt-get update \
&& apt-get -y install --no-install-recommends espeak postgresql-client libc6 libssl1.1 \ && apt-get -y install --no-install-recommends postgresql-client libc6 libssl1.1 \
&& rm -rf /var/lib/apt/lists/* && rm -rf /var/lib/apt/lists/*
RUN addgroup --gid 1000 lemmy RUN addgroup --gid 1000 lemmy