mirror of
https://github.com/mCaptcha/cache.git
synced 2024-11-28 11:58:42 +03:00
working free
This commit is contained in:
parent
158f518449
commit
7bc8d4fcfb
3 changed files with 73 additions and 41 deletions
|
@ -18,6 +18,10 @@ use redis_module::{redis_command, redis_module};
|
||||||
use redis_module::{Context, NextArg, RedisResult};
|
use redis_module::{Context, NextArg, RedisResult};
|
||||||
|
|
||||||
mod pocket;
|
mod pocket;
|
||||||
|
mod utils;
|
||||||
|
|
||||||
|
use pocket::MCAPTCHA_POCKET_TYPE;
|
||||||
|
|
||||||
fn timer_create(ctx: &Context, args: Vec<String>) -> RedisResult {
|
fn timer_create(ctx: &Context, args: Vec<String>) -> RedisResult {
|
||||||
let mut args = args.into_iter().skip(1);
|
let mut args = args.into_iter().skip(1);
|
||||||
// mcaptcha captcha key name
|
// mcaptcha captcha key name
|
||||||
|
@ -35,8 +39,8 @@ fn timer_create(ctx: &Context, args: Vec<String>) -> RedisResult {
|
||||||
redis_module! {
|
redis_module! {
|
||||||
name: "mcaptcha_cahce",
|
name: "mcaptcha_cahce",
|
||||||
version: 1,
|
version: 1,
|
||||||
data_types: [],
|
data_types: [MCAPTCHA_POCKET_TYPE,],
|
||||||
commands: [
|
commands: [
|
||||||
["mcaptcha_cahce.create", timer_create, "", 0, 0, 0],
|
["mcaptcha_cahce.create", timer_create, "write", 1, 1, 1],
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,48 +15,33 @@
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use std::collections::HashMap;
|
|
||||||
use std::os::raw::c_void;
|
use std::os::raw::c_void;
|
||||||
use std::time::{Duration, SystemTime, UNIX_EPOCH};
|
use std::time::Duration;
|
||||||
|
|
||||||
use redis_module::native_types::RedisType;
|
use redis_module::native_types::RedisType;
|
||||||
use redis_module::raw::KeyType;
|
use redis_module::raw::KeyType;
|
||||||
use redis_module::RedisError;
|
use redis_module::RedisError;
|
||||||
use redis_module::{raw, Context};
|
use redis_module::{raw, Context};
|
||||||
|
|
||||||
pub const PREFIX_COUNTER: &str = "mcaptcha_cache:captcha:";
|
use crate::utils::*;
|
||||||
pub const PREFIX_TIME_POCKET: &str = "mcaptcha_cache:pocket:";
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct Pocket {
|
pub struct Pocket {
|
||||||
timer: Option<u64>,
|
timer: Option<u64>,
|
||||||
pocket_instant: u64,
|
pocket_instant: u64,
|
||||||
decrement: HashMap<String, usize>,
|
decrement: Vec<(String, u32)>,
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
/// duration in seconds
|
|
||||||
fn get_pocket_name(pocket_instant: u64) -> String {
|
|
||||||
format!("{}{}", PREFIX_TIME_POCKET, pocket_instant)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn pocket_instant(duration: u64) -> Result<u64, RedisError> {
|
|
||||||
match SystemTime::now().duration_since(UNIX_EPOCH) {
|
|
||||||
Ok(val) => Ok(val.as_secs() + duration),
|
|
||||||
Err(_) => Err(RedisError::String("SystemTime before UNIX EPOCH!".into())),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn get_captcha_key(name: &str) -> String {
|
|
||||||
format!("{}{}", PREFIX_COUNTER, name)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Pocket {
|
impl Pocket {
|
||||||
|
#[inline]
|
||||||
|
fn get_mut<'a>(v: &'a mut Vec<(String, u32)>, query: &str) -> Option<&'a mut (String, u32)> {
|
||||||
|
v.iter_mut()
|
||||||
|
.find(|(name, _)| if name == query { true } else { false })
|
||||||
|
}
|
||||||
|
|
||||||
/// creates new pocket and sets off timer to go off at `duration`
|
/// creates new pocket and sets off timer to go off at `duration`
|
||||||
pub fn new(ctx: &Context, duration: u64) -> Result<Self, RedisError> {
|
pub fn new(ctx: &Context, duration: u64) -> Result<Self, RedisError> {
|
||||||
let decrement = HashMap::new();
|
let decrement = Vec::with_capacity(1);
|
||||||
|
|
||||||
let pocket_instant = pocket_instant(duration)?;
|
let pocket_instant = pocket_instant(duration)?;
|
||||||
let timer = Some(ctx.create_timer(
|
let timer = Some(ctx.create_timer(
|
||||||
|
@ -102,18 +87,18 @@ impl Pocket {
|
||||||
let pocket = ctx.open_key_writable(&pocket_name);
|
let pocket = ctx.open_key_writable(&pocket_name);
|
||||||
|
|
||||||
match pocket.get_value::<Pocket>(&MCAPTCHA_POCKET_TYPE)? {
|
match pocket.get_value::<Pocket>(&MCAPTCHA_POCKET_TYPE)? {
|
||||||
Some(pocket) => match pocket.decrement.get_mut(&captcha_name) {
|
Some(pocket) => match Self::get_mut(&mut pocket.decrement, &captcha_name) {
|
||||||
Some(count) => *count += 1,
|
Some((_name, count)) => *count += 1,
|
||||||
None => {
|
None => {
|
||||||
pocket.decrement.insert(captcha_name, 1);
|
pocket.decrement.push((captcha_name, 1));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
None => {
|
None => {
|
||||||
let mut counter = Pocket::new(ctx, duration)?;
|
let mut counter = Pocket::new(ctx, duration)?;
|
||||||
counter.decrement.insert(captcha_name, 1);
|
counter.decrement.push((captcha_name, 1));
|
||||||
pocket.set_value(&MCAPTCHA_POCKET_TYPE, counter)?;
|
pocket.set_value(&MCAPTCHA_POCKET_TYPE, counter)?;
|
||||||
pocket.set_expire(Duration::from_secs(duration + 10))?;
|
// pocket.set_expire(Duration::from_secs(duration + 10))?;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -132,7 +117,7 @@ impl Pocket {
|
||||||
match val {
|
match val {
|
||||||
Some(pocket) => {
|
Some(pocket) => {
|
||||||
ctx.log_warning(&format!("entering loop hashmap "));
|
ctx.log_warning(&format!("entering loop hashmap "));
|
||||||
for (captcha, count) in pocket.decrement.drain() {
|
for (captcha, count) in pocket.decrement.iter() {
|
||||||
ctx.log_warning(&format!(
|
ctx.log_warning(&format!(
|
||||||
"reading captcha: {} with decr count {}",
|
"reading captcha: {} with decr count {}",
|
||||||
&captcha, count
|
&captcha, count
|
||||||
|
@ -142,7 +127,7 @@ impl Pocket {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut stored_count: usize =
|
let mut stored_count: u32 =
|
||||||
stored_captcha.read().unwrap().unwrap().parse().unwrap();
|
stored_captcha.read().unwrap().unwrap().parse().unwrap();
|
||||||
stored_count -= count;
|
stored_count -= count;
|
||||||
stored_captcha.write(&stored_count.to_string()).unwrap();
|
stored_captcha.write(&stored_count.to_string()).unwrap();
|
||||||
|
@ -156,16 +141,18 @@ impl Pocket {
|
||||||
ctx.log_warning(&format!("loop exited"));
|
ctx.log_warning(&format!("loop exited"));
|
||||||
let res = key.delete();
|
let res = key.delete();
|
||||||
|
|
||||||
|
if res.is_err() {
|
||||||
ctx.log_warning(&format!(
|
ctx.log_warning(&format!(
|
||||||
"enountered error while deleting hashmap: {:?}",
|
"enountered error while deleting hashmap: {:?}",
|
||||||
res
|
res
|
||||||
));
|
));
|
||||||
//res.unwrap();
|
}
|
||||||
|
res.unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static MCAPTCHA_POCKET_TYPE: RedisType = RedisType::new(
|
pub static MCAPTCHA_POCKET_TYPE: RedisType = RedisType::new(
|
||||||
"mcaptcha_cache_pocket",
|
"mcaptchac",
|
||||||
0,
|
0,
|
||||||
raw::RedisModuleTypeMethods {
|
raw::RedisModuleTypeMethods {
|
||||||
version: raw::REDISMODULE_TYPE_METHOD_VERSION as u64,
|
version: raw::REDISMODULE_TYPE_METHOD_VERSION as u64,
|
||||||
|
|
41
src/utils.rs
Normal file
41
src/utils.rs
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 Aravinth Manivannan <realaravinth@batsense.net>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as
|
||||||
|
* published by the Free Software Foundation, either version 3 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
use std::time::{SystemTime, UNIX_EPOCH};
|
||||||
|
|
||||||
|
use redis_module::RedisError;
|
||||||
|
|
||||||
|
pub const PREFIX_COUNTER: &str = "mcaptcha_cache:captcha:";
|
||||||
|
pub const PREFIX_TIME_POCKET: &str = "mcaptcha_cache:pocket:";
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
/// duration in seconds
|
||||||
|
pub fn get_pocket_name(pocket_instant: u64) -> String {
|
||||||
|
format!("{}{}", PREFIX_TIME_POCKET, pocket_instant)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn pocket_instant(duration: u64) -> Result<u64, RedisError> {
|
||||||
|
match SystemTime::now().duration_since(UNIX_EPOCH) {
|
||||||
|
Ok(val) => Ok(val.as_secs() + duration),
|
||||||
|
Err(_) => Err(RedisError::String("SystemTime before UNIX EPOCH!".into())),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn get_captcha_key(name: &str) -> String {
|
||||||
|
format!("{}{}", PREFIX_COUNTER, name)
|
||||||
|
}
|
Loading…
Reference in a new issue