Implements Request Limit with Redis

This commit is contained in:
2024-02-26 01:03:26 -03:00
parent b1a223f0a4
commit ee6f242667
15 changed files with 220 additions and 11 deletions

View File

@@ -1,16 +1,30 @@
use std::collections::BTreeMap;
use redis::{AsyncCommands, ExistenceCheck, SetExpiry, SetOptions};
use crate::config::config_auth::ConfigAuth;
use crate::model::send_message::MessageAuthor;
use reqwest::header::AUTHORIZATION;
use crate::config::config_limits::ConfigLimits;
use crate::config::config_redis::ConfigRedis;
#[derive(Clone)]
pub struct AuthService {
auth_url: String,
redis: redis::Client,
max_requests: u32,
expiration_time: usize,
}
impl AuthService {
pub fn new(config_auth: ConfigAuth) -> Self {
pub fn new(config_auth: ConfigAuth, config_redis: ConfigRedis, limits: ConfigLimits) -> Self {
let client = redis::Client::open(
format!("redis://{}:{}", config_redis.redis_url, config_redis.redis_port).as_str()
).unwrap();
AuthService {
auth_url: config_auth.auth_url,
redis: client,
max_requests: limits.max_requests,
expiration_time: limits.expiration_time,
}
}
@@ -34,4 +48,48 @@ impl AuthService {
None
}
pub async fn has_user_reached_limit(&self, user: &MessageAuthor) -> bool {
let user_requests = self.count_user_requests(user).await;
return user_requests >= self.max_requests;
}
pub async fn increase_user_request(&self, user: &MessageAuthor) -> bool {
let mut con = self.redis.get_async_connection().await.unwrap();
let current_request_key= format!(
"user-message:{}:requests:{}",
user.email,
chrono::Utc::now().timestamp()
);
let set_options = SetOptions::default()
.with_expiration(SetExpiry::EX(self.expiration_time))
.conditional_set(ExistenceCheck::NX)
.get(false);
return con.set_options(
&current_request_key,
1,
set_options
).await.expect("Error setting key");
}
async fn count_user_requests(&self, user: &MessageAuthor) -> u32 {
let mut con = self.redis.get_async_connection().await.unwrap();
let query_user_requests = format!("user-message:{}:requests:*", user.email);
let results: Vec<String>;
match con.keys(query_user_requests).await {
Ok(r) => {
results = r;
},
Err(e) => {
return 0;
}
};
return results.len() as u32;
}
}