Working but untested captcha api
This commit is contained in:
parent
4c398a40f6
commit
fa9b2b6fc1
8 changed files with 107 additions and 12 deletions
|
@ -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>,
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue