Working but untested captcha api

This commit is contained in:
Imbus 2023-10-21 05:11:42 +02:00
parent 4c398a40f6
commit fa9b2b6fc1
8 changed files with 107 additions and 12 deletions

View file

@ -41,7 +41,7 @@ pub struct User {
// Note that these are optional
/// Query parameters for the /posts endpoint
#[derive(Debug, Serialize, Deserialize)]
struct QueryParams {
pub struct QueryParams {
limit: Option<i64>,
offset: Option<i64>,
}

View file

@ -1,14 +1,16 @@
use crate::jwt::token_factory;
use crate::state::CaptchaState;
use crate::ServerState;
use actix_web::web::Data;
use actix_web::{post, web::Json, HttpResponse, Responder, Result};
use argon2::password_hash::rand_core::OsRng;
use argon2::password_hash::rand_core::{OsRng, RngCore};
use argon2::password_hash::SaltString;
use argon2::password_hash::*;
use argon2::Argon2;
use argon2::PasswordHasher;
use argon2::PasswordVerifier;
use biosvg::BiosvgBuilder;
use log::*;
use serde::{Deserialize, Serialize};
@ -101,7 +103,7 @@ pub async fn login(data: Json<LoginData>, state: Data<ServerState>) -> Result<im
println!("{:?}", token);
return Ok(HttpResponse::Ok().json(LoginResponse {
username: data.username.clone(),
token: token,
token,
}));
}
Err(_) => {
@ -110,3 +112,59 @@ pub async fn login(data: Json<LoginData>, state: Data<ServerState>) -> Result<im
}
}
}
#[derive(Debug, Serialize, Deserialize)]
pub struct CaptchaResponse {
captcha_svg: String,
captcha_id: i32,
}
/// Request a captcha from the captcha service
#[post("/captcha")]
pub async fn captcha_request(cstate: Data<CaptchaState>) -> Result<impl Responder> {
// This might block the thread a bit too long
let (answer, svg) = get_captcha();
let id = rand_core::OsRng.next_u32() as i32;
let cresponse = CaptchaResponse {
captcha_svg: svg.clone(),
captcha_id: id,
};
// This is bad in about every way i can think of
// It might just be better to hit the database every time, and let the database
// handle rng and maybe set a trigger to delete old captchas
match cstate.capthca_db.lock() {
Ok(mut db) => {
if (db.len() as i32) > 100 {
// To prevent the database from growing too large
// Replace with a proper LRU cache or circular buffer
db.remove(&(id % 100)); // This is terrible
}
db.insert(id, answer.clone()); // We do not care about collisions
return Ok(HttpResponse::Ok().json(cresponse));
}
Err(_) => {
// This shouldnt happen
error!("Failed to lock captcha database");
return Ok(HttpResponse::InternalServerError().json("Error"));
}
}
}
/// Returns a new captcha in the form of a tuple (answer, svg)
fn get_captcha() -> (String, String) {
BiosvgBuilder::new()
.length(4)
.difficulty(6)
.colors(vec![
"#0078D6".to_string(),
"#aa3333".to_string(),
"#f08012".to_string(),
"#33aa00".to_string(),
"#aa33aa".to_string(),
])
.build()
.unwrap()
}