Add rate limiting

This commit is contained in:
2023-05-26 17:55:19 +02:00
parent 4ba4d10fce
commit c84c2ef3c5
14 changed files with 242 additions and 31 deletions

View File

@ -1,7 +1,8 @@
use crate::constants::StaticConstraints;
use crate::services::users_service;
use crate::controllers::HttpResult;
use crate::services::rate_limiter_service::RatedAction;
use crate::services::{rate_limiter_service, users_service};
use actix_remote_ip::RemoteIP;
use actix_web::error::ErrorInternalServerError;
use actix_web::{web, HttpResponse};
#[derive(serde::Deserialize)]
@ -11,11 +12,12 @@ pub struct CreateAccountBody {
}
/// Create a new account
pub async fn create_account(
_remote_ip: RemoteIP,
req: web::Json<CreateAccountBody>,
) -> actix_web::Result<HttpResponse> {
// TODO : rate limiting
pub async fn create_account(remote_ip: RemoteIP, req: web::Json<CreateAccountBody>) -> HttpResult {
// Rate limiting
if rate_limiter_service::should_block_action(remote_ip.0, RatedAction::CreateAccount).await? {
return Ok(HttpResponse::TooManyRequests().finish());
}
rate_limiter_service::record_action(remote_ip.0, RatedAction::CreateAccount).await?;
// Check if email is valid
if !mailchecker::is_valid(&req.email) {
@ -30,25 +32,14 @@ pub async fn create_account(
}
// Check if email is already attached to an account
match users_service::exists_email(&req.email).await {
Ok(false) => {}
Ok(true) => {
return Ok(HttpResponse::Conflict()
.json("An account with the same email address already exists!"));
}
Err(e) => {
log::error!("Failed to check email existence! {}", e);
return Err(ErrorInternalServerError(e));
}
if users_service::exists_email(&req.email).await? {
return Ok(
HttpResponse::Conflict().json("An account with the same email address already exists!")
);
}
// Create the account
let user_id = users_service::create_account(&req.name, &req.email)
.await
.map_err(|e| {
log::error!("Failed to create user! {e}");
ErrorInternalServerError(e)
})?;
let user_id = users_service::create_account(&req.name, &req.email).await?;
// TODO : trigger reset password (send mail)

View File

@ -0,0 +1,35 @@
//! # API controller
use actix_web::body::BoxBody;
use actix_web::HttpResponse;
use std::fmt::{Debug, Display, Formatter};
pub mod auth_controller;
pub mod config_controller;
/// Custom error to ease controller writing
#[derive(Debug)]
pub struct HttpErr {
err: anyhow::Error,
}
impl Display for HttpErr {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
std::fmt::Display::fmt(&self.err, f)
}
}
impl actix_web::error::ResponseError for HttpErr {
fn error_response(&self) -> HttpResponse<BoxBody> {
log::error!("Error while processing request! {}", self);
HttpResponse::InternalServerError().body("Failed to execute request!")
}
}
impl From<anyhow::Error> for HttpErr {
fn from(err: anyhow::Error) -> HttpErr {
HttpErr { err }
}
}
pub type HttpResult = Result<HttpResponse, HttpErr>;