extending Save to cache captcha responses
This commit is contained in:
parent
61ee89aee3
commit
b597c0b965
7 changed files with 141 additions and 29 deletions
10
CHANGELOG.md
10
CHANGELOG.md
|
@ -2,6 +2,16 @@
|
||||||
## Fixed
|
## Fixed
|
||||||
- a bug in `mCaptcha/pow_sha256` was causing errors in PoW computation
|
- a bug in `mCaptcha/pow_sha256` was causing errors in PoW computation
|
||||||
|
|
||||||
|
## Changed
|
||||||
|
- `Cache` became `CachePoW` (`HashCache` extension)
|
||||||
|
- `Retrieve` became `RetrievePoW`(`HashCache` extension)
|
||||||
|
- `DeleteString` became `DeletePoW` (`HashCache` extension)
|
||||||
|
- `Save` trait now requires three new message impls (`HashCache` extension_
|
||||||
|
|
||||||
|
## Added
|
||||||
|
- `HashCache` was extended to store captcha responses
|
||||||
|
|
||||||
|
|
||||||
## 0.1.2
|
## 0.1.2
|
||||||
## Changed
|
## Changed
|
||||||
- actix upgraded to `0.11`
|
- actix upgraded to `0.11`
|
||||||
|
|
89
Cargo.lock
generated
89
Cargo.lock
generated
|
@ -76,6 +76,15 @@ dependencies = [
|
||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "aho-corasick"
|
||||||
|
version = "0.7.15"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7404febffaa47dac81aa44dba71523c9d069b1bdc50a77db41195149e17f68e5"
|
||||||
|
dependencies = [
|
||||||
|
"memchr",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "async-trait"
|
name = "async-trait"
|
||||||
version = "0.1.48"
|
version = "0.1.48"
|
||||||
|
@ -87,6 +96,17 @@ dependencies = [
|
||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "atty"
|
||||||
|
version = "0.2.14"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
|
||||||
|
dependencies = [
|
||||||
|
"hermit-abi",
|
||||||
|
"libc",
|
||||||
|
"winapi 0.3.9",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "autocfg"
|
name = "autocfg"
|
||||||
version = "1.0.1"
|
version = "1.0.1"
|
||||||
|
@ -341,6 +361,19 @@ dependencies = [
|
||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "env_logger"
|
||||||
|
version = "0.7.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36"
|
||||||
|
dependencies = [
|
||||||
|
"atty",
|
||||||
|
"humantime",
|
||||||
|
"log",
|
||||||
|
"regex",
|
||||||
|
"termcolor",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fnv"
|
name = "fnv"
|
||||||
version = "1.0.7"
|
version = "1.0.7"
|
||||||
|
@ -499,6 +532,15 @@ dependencies = [
|
||||||
"winapi 0.3.9",
|
"winapi 0.3.9",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "humantime"
|
||||||
|
version = "1.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f"
|
||||||
|
dependencies = [
|
||||||
|
"quick-error",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ident_case"
|
name = "ident_case"
|
||||||
version = "1.0.1"
|
version = "1.0.1"
|
||||||
|
@ -615,7 +657,9 @@ dependencies = [
|
||||||
"actix-rt",
|
"actix-rt",
|
||||||
"derive_builder 0.9.0",
|
"derive_builder 0.9.0",
|
||||||
"derive_more",
|
"derive_more",
|
||||||
|
"log",
|
||||||
"pow_sha256",
|
"pow_sha256",
|
||||||
|
"pretty_env_logger",
|
||||||
"rand 0.8.3",
|
"rand 0.8.3",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
|
@ -806,6 +850,16 @@ version = "0.2.10"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857"
|
checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pretty_env_logger"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "926d36b9553851b8b0005f1275891b392ee4d2d833852c417ed025477350fb9d"
|
||||||
|
dependencies = [
|
||||||
|
"env_logger",
|
||||||
|
"log",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro2"
|
name = "proc-macro2"
|
||||||
version = "1.0.26"
|
version = "1.0.26"
|
||||||
|
@ -920,6 +974,23 @@ dependencies = [
|
||||||
"bitflags",
|
"bitflags",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "regex"
|
||||||
|
version = "1.4.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "957056ecddbeba1b26965114e191d2e8589ce74db242b6ea25fc4062427a5c19"
|
||||||
|
dependencies = [
|
||||||
|
"aho-corasick",
|
||||||
|
"memchr",
|
||||||
|
"regex-syntax",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "regex-syntax"
|
||||||
|
version = "0.6.23"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "24d5f089152e60f62d28b835fbff2cd2e8dc0baf1ac13343bef92ab7eed84548"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "resolv-conf"
|
name = "resolv-conf"
|
||||||
version = "0.7.0"
|
version = "0.7.0"
|
||||||
|
@ -1041,6 +1112,15 @@ dependencies = [
|
||||||
"unicode-xid",
|
"unicode-xid",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "termcolor"
|
||||||
|
version = "1.1.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4"
|
||||||
|
dependencies = [
|
||||||
|
"winapi-util",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "thiserror"
|
name = "thiserror"
|
||||||
version = "1.0.24"
|
version = "1.0.24"
|
||||||
|
@ -1260,6 +1340,15 @@ version = "0.4.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi-util"
|
||||||
|
version = "0.1.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
|
||||||
|
dependencies = [
|
||||||
|
"winapi 0.3.9",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "winapi-x86_64-pc-windows-gnu"
|
name = "winapi-x86_64-pc-windows-gnu"
|
||||||
version = "0.4.0"
|
version = "0.4.0"
|
||||||
|
|
|
@ -16,6 +16,9 @@ actix = "0.10"
|
||||||
serde = "1.0.114"
|
serde = "1.0.114"
|
||||||
serde_json = "1"
|
serde_json = "1"
|
||||||
|
|
||||||
|
pretty_env_logger = "0.4"
|
||||||
|
log = "0.4"
|
||||||
|
|
||||||
derive_builder = "0.9"
|
derive_builder = "0.9"
|
||||||
derive_more = "0.99"
|
derive_more = "0.99"
|
||||||
|
|
||||||
|
|
42
src/cache/hashcache.rs
vendored
42
src/cache/hashcache.rs
vendored
|
@ -26,12 +26,16 @@ use crate::errors::*;
|
||||||
|
|
||||||
#[derive(Clone, Default)]
|
#[derive(Clone, Default)]
|
||||||
/// cache datastructure implementing [Save]
|
/// cache datastructure implementing [Save]
|
||||||
pub struct HashCache(HashMap<String, u32>);
|
pub struct HashCache {
|
||||||
|
difficulty_map: HashMap<String, u32>,
|
||||||
|
result_map: HashMap<String, String>,
|
||||||
|
}
|
||||||
|
|
||||||
impl HashCache {
|
impl HashCache {
|
||||||
// save [PoWConfig] to cache
|
// save [PoWConfig] to cache
|
||||||
fn save(&mut self, config: Cache) -> CaptchaResult<()> {
|
fn save(&mut self, config: CachePoW) -> CaptchaResult<()> {
|
||||||
self.0.insert(config.string, config.difficulty_factor);
|
self.difficulty_map
|
||||||
|
.insert(config.string, config.difficulty_factor);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,7 +50,7 @@ impl HashCache {
|
||||||
|
|
||||||
// delete [PoWConfig] from cache
|
// delete [PoWConfig] from cache
|
||||||
fn remove(&mut self, string: &str) -> Option<u32> {
|
fn remove(&mut self, string: &str) -> Option<u32> {
|
||||||
self.0.remove(string)
|
self.difficulty_map.remove(string)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,15 +61,15 @@ impl Actor for HashCache {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// cache a PoWConfig
|
/// cache a PoWConfig
|
||||||
impl Handler<Cache> for HashCache {
|
impl Handler<CachePoW> for HashCache {
|
||||||
type Result = MessageResult<Cache>;
|
type Result = MessageResult<CachePoW>;
|
||||||
fn handle(&mut self, msg: Cache, ctx: &mut Self::Context) -> Self::Result {
|
fn handle(&mut self, msg: CachePoW, ctx: &mut Self::Context) -> Self::Result {
|
||||||
//use actix::clock::sleep;
|
//use actix::clock::sleep;
|
||||||
use actix::clock::delay_for;
|
use actix::clock::delay_for;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
let addr = ctx.address();
|
let addr = ctx.address();
|
||||||
let del_msg = DeleteString(msg.string.clone());
|
let del_msg = DeletePoW(msg.string.clone());
|
||||||
|
|
||||||
let duration: Duration = Duration::new(msg.duration.clone(), 0);
|
let duration: Duration = Duration::new(msg.duration.clone(), 0);
|
||||||
let wait_for = async move {
|
let wait_for = async move {
|
||||||
|
@ -81,18 +85,18 @@ impl Handler<Cache> for HashCache {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Delte a PoWConfig
|
/// Delte a PoWConfig
|
||||||
impl Handler<DeleteString> for HashCache {
|
impl Handler<DeletePoW> for HashCache {
|
||||||
type Result = MessageResult<DeleteString>;
|
type Result = MessageResult<DeletePoW>;
|
||||||
fn handle(&mut self, msg: DeleteString, _ctx: &mut Self::Context) -> Self::Result {
|
fn handle(&mut self, msg: DeletePoW, _ctx: &mut Self::Context) -> Self::Result {
|
||||||
self.remove(&msg.0);
|
self.remove(&msg.0);
|
||||||
MessageResult(Ok(()))
|
MessageResult(Ok(()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Retrive PoW difficulty_factor for a PoW string
|
/// Retrive PoW difficulty_factor for a PoW string
|
||||||
impl Handler<Retrive> for HashCache {
|
impl Handler<RetrivePoW> for HashCache {
|
||||||
type Result = MessageResult<Retrive>;
|
type Result = MessageResult<RetrivePoW>;
|
||||||
fn handle(&mut self, msg: Retrive, _ctx: &mut Self::Context) -> Self::Result {
|
fn handle(&mut self, msg: RetrivePoW, _ctx: &mut Self::Context) -> Self::Result {
|
||||||
MessageResult(self.retrive(msg.0))
|
MessageResult(self.retrive(msg.0))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -127,18 +131,22 @@ mod tests {
|
||||||
duration: DURATION,
|
duration: DURATION,
|
||||||
};
|
};
|
||||||
let string = pow.string.clone();
|
let string = pow.string.clone();
|
||||||
let msg = Cache::new(&pow, &visitor_result);
|
let msg = CachePoW::new(&pow, &visitor_result);
|
||||||
|
|
||||||
addr.send(msg).await.unwrap().unwrap();
|
addr.send(msg).await.unwrap().unwrap();
|
||||||
|
|
||||||
let cache_difficulty_factor = addr.send(Retrive(string.clone())).await.unwrap().unwrap();
|
let cache_difficulty_factor = addr
|
||||||
|
.send(RetrivePoW(string.clone()))
|
||||||
|
.await
|
||||||
|
.unwrap()
|
||||||
|
.unwrap();
|
||||||
assert_eq!(DIFFICULTY_FACTOR, cache_difficulty_factor.unwrap());
|
assert_eq!(DIFFICULTY_FACTOR, cache_difficulty_factor.unwrap());
|
||||||
|
|
||||||
let duration: Duration = Duration::new(5, 0);
|
let duration: Duration = Duration::new(5, 0);
|
||||||
//sleep(DURATION + DURATION).await;
|
//sleep(DURATION + DURATION).await;
|
||||||
delay_for(duration + duration).await;
|
delay_for(duration + duration).await;
|
||||||
|
|
||||||
let expired_string = addr.send(Retrive(string)).await.unwrap().unwrap();
|
let expired_string = addr.send(RetrivePoW(string)).await.unwrap().unwrap();
|
||||||
assert_eq!(None, expired_string);
|
assert_eq!(None, expired_string);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
12
src/cache/mod.rs
vendored
12
src/cache/mod.rs
vendored
|
@ -24,7 +24,7 @@ pub mod hashcache;
|
||||||
|
|
||||||
/// Describes actor handler trait impls that are required by a cache implementation
|
/// Describes actor handler trait impls that are required by a cache implementation
|
||||||
pub trait Save:
|
pub trait Save:
|
||||||
actix::Actor + actix::Handler<Retrive> + actix::Handler<Cache> + actix::Handler<DeleteString>
|
actix::Actor + actix::Handler<RetrivePoW> + actix::Handler<CachePoW> + actix::Handler<DeletePoW>
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
pub mod messages {
|
pub mod messages {
|
||||||
|
@ -40,15 +40,15 @@ pub mod messages {
|
||||||
/// Message to cache PoW difficulty factor and string
|
/// Message to cache PoW difficulty factor and string
|
||||||
#[derive(Message, Serialize, Deserialize, Builder)]
|
#[derive(Message, Serialize, Deserialize, Builder)]
|
||||||
#[rtype(result = "CaptchaResult<()>")]
|
#[rtype(result = "CaptchaResult<()>")]
|
||||||
pub struct Cache {
|
pub struct CachePoW {
|
||||||
pub string: String,
|
pub string: String,
|
||||||
pub difficulty_factor: u32,
|
pub difficulty_factor: u32,
|
||||||
pub duration: u64,
|
pub duration: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Cache {
|
impl CachePoW {
|
||||||
pub fn new(p: &PoWConfig, v: &AddVisitorResult) -> Self {
|
pub fn new(p: &PoWConfig, v: &AddVisitorResult) -> Self {
|
||||||
CacheBuilder::default()
|
CachePoWBuilder::default()
|
||||||
.string(p.string.clone())
|
.string(p.string.clone())
|
||||||
.difficulty_factor(v.difficulty_factor)
|
.difficulty_factor(v.difficulty_factor)
|
||||||
.duration(v.duration)
|
.duration(v.duration)
|
||||||
|
@ -61,11 +61,11 @@ pub mod messages {
|
||||||
/// string from the cache
|
/// string from the cache
|
||||||
#[derive(Message)]
|
#[derive(Message)]
|
||||||
#[rtype(result = "CaptchaResult<Option<u32>>")]
|
#[rtype(result = "CaptchaResult<Option<u32>>")]
|
||||||
pub struct Retrive(pub String);
|
pub struct RetrivePoW(pub String);
|
||||||
|
|
||||||
/// Message to delete cached PoW difficulty factor and string
|
/// Message to delete cached PoW difficulty factor and string
|
||||||
/// when they expire
|
/// when they expire
|
||||||
#[derive(Message)]
|
#[derive(Message)]
|
||||||
#[rtype(result = "CaptchaResult<()>")]
|
#[rtype(result = "CaptchaResult<()>")]
|
||||||
pub struct DeleteString(pub String);
|
pub struct DeletePoW(pub String);
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,7 @@ use std::time::Duration;
|
||||||
use actix::clock::delay_for;
|
use actix::clock::delay_for;
|
||||||
use actix::dev::*;
|
use actix::dev::*;
|
||||||
use derive_builder::Builder;
|
use derive_builder::Builder;
|
||||||
|
use log::info;
|
||||||
|
|
||||||
use crate::mcaptcha::MCaptcha;
|
use crate::mcaptcha::MCaptcha;
|
||||||
|
|
||||||
|
@ -111,7 +112,7 @@ impl Handler<CleanUp> for Master {
|
||||||
let sites = self.sites.clone();
|
let sites = self.sites.clone();
|
||||||
let gc = self.gc;
|
let gc = self.gc;
|
||||||
let master = ctx.address();
|
let master = ctx.address();
|
||||||
println!("init cleanup up");
|
info!("init master actor cleanup up");
|
||||||
let task = async move {
|
let task = async move {
|
||||||
for (id, (new, addr)) in sites.iter() {
|
for (id, (new, addr)) in sites.iter() {
|
||||||
use crate::mcaptcha::{GetCurrentVisitorCount, Stop};
|
use crate::mcaptcha::{GetCurrentVisitorCount, Stop};
|
||||||
|
|
|
@ -37,11 +37,12 @@ pub struct System<T: Save> {
|
||||||
impl<T> System<T>
|
impl<T> System<T>
|
||||||
where
|
where
|
||||||
T: Save,
|
T: Save,
|
||||||
<T as actix::Actor>::Context: ToEnvelope<T, messages::Cache> + ToEnvelope<T, messages::Retrive>,
|
<T as actix::Actor>::Context:
|
||||||
|
ToEnvelope<T, messages::CachePoW> + ToEnvelope<T, messages::RetrivePoW>,
|
||||||
{
|
{
|
||||||
/// utility function to get difficulty factor of site `id` and cache it
|
/// utility function to get difficulty factor of site `id` and cache it
|
||||||
pub async fn get_pow(&self, id: String) -> Option<PoWConfig> {
|
pub async fn get_pow(&self, id: String) -> Option<PoWConfig> {
|
||||||
use crate::cache::messages::Cache;
|
use crate::cache::messages::CachePoW;
|
||||||
use crate::master::GetSite;
|
use crate::master::GetSite;
|
||||||
use crate::mcaptcha::AddVisitor;
|
use crate::mcaptcha::AddVisitor;
|
||||||
|
|
||||||
|
@ -52,17 +53,17 @@ where
|
||||||
let mcaptcha = site_addr.unwrap().send(AddVisitor).await.unwrap();
|
let mcaptcha = site_addr.unwrap().send(AddVisitor).await.unwrap();
|
||||||
let pow_config = PoWConfig::new(mcaptcha.difficulty_factor);
|
let pow_config = PoWConfig::new(mcaptcha.difficulty_factor);
|
||||||
|
|
||||||
let cache_msg = Cache::new(&pow_config, &mcaptcha);
|
let cache_msg = CachePoW::new(&pow_config, &mcaptcha);
|
||||||
self.cache.send(cache_msg).await.unwrap().unwrap();
|
self.cache.send(cache_msg).await.unwrap().unwrap();
|
||||||
Some(pow_config)
|
Some(pow_config)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// utility function to verify [Work]
|
/// utility function to verify [Work]
|
||||||
pub async fn verify_pow(&self, work: Work) -> CaptchaResult<bool> {
|
pub async fn verify_pow(&self, work: Work) -> CaptchaResult<bool> {
|
||||||
use crate::cache::messages::Retrive;
|
use crate::cache::messages::RetrivePoW;
|
||||||
|
|
||||||
let string = work.string.clone();
|
let string = work.string.clone();
|
||||||
let msg = Retrive(string.clone());
|
let msg = RetrivePoW(string.clone());
|
||||||
let pow: PoW<String> = work.into();
|
let pow: PoW<String> = work.into();
|
||||||
|
|
||||||
let difficulty = self.cache.send(msg).await.unwrap()?;
|
let difficulty = self.cache.send(msg).await.unwrap()?;
|
||||||
|
|
Loading…
Reference in a new issue