redis storage for captcha mech

This commit is contained in:
realaravinth
2021-06-11 19:31:03 +05:30
parent 17ae532162
commit f5624947b9
29 changed files with 604 additions and 210 deletions

View File

@@ -14,30 +14,86 @@
* 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::sync::Arc;
use actix::prelude::*;
use argon2_creds::{Config, ConfigBuilder, PasswordPolicy};
use libmcaptcha::cache::hashcache::HashCache;
use libmcaptcha::cache::redis::RedisCache;
use libmcaptcha::master::redis::master::Master as RedisMaster;
use libmcaptcha::redis::RedisConfig;
use libmcaptcha::{
cache::HashCache,
master::Master,
cache::messages::VerifyCaptchaResult,
cache::Save,
errors::CaptchaResult,
master::{embedded::master::Master as EmbeddedMaster, Master as MasterTrait},
pow::ConfigBuilder as PoWConfigBuilder,
pow::PoWConfig,
pow::Work,
system::{System, SystemBuilder},
// master::messages::AddSite,
};
use sqlx::postgres::PgPoolOptions;
use sqlx::PgPool;
use crate::SETTINGS;
#[derive(Clone)]
pub struct Data {
pub db: PgPool,
pub creds: Config,
pub captcha: System<HashCache>,
pub captcha: SystemGroup,
}
pub enum SystemGroup {
Embedded(System<HashCache, EmbeddedMaster>),
Redis(System<RedisCache, RedisMaster>),
}
impl SystemGroup {
/// utility function to get difficulty factor of site `id` and cache it
pub async fn get_pow(&self, id: String) -> Option<PoWConfig> {
match self {
Self::Embedded(val) => val.get_pow(id).await,
Self::Redis(val) => val.get_pow(id).await,
}
}
/// utility function to verify [Work]
pub async fn verify_pow(&self, work: Work) -> CaptchaResult<String> {
match self {
Self::Embedded(val) => val.verify_pow(work).await,
Self::Redis(val) => val.verify_pow(work).await,
}
}
/// utility function to validate verification tokens
pub async fn validate_verification_tokens(
&self,
msg: VerifyCaptchaResult,
) -> CaptchaResult<bool> {
match self {
Self::Embedded(val) => val.validate_verification_tokens(msg).await,
Self::Redis(val) => val.validate_verification_tokens(msg).await,
}
}
// /// utility function to AddSite
// pub async fn add_site(
// &self,
// msg: AddSite,
// ) -> CaptchaResult<()> {
// match self {
// Self::Embedded(val) => val.master.send(msg).await?,
// Self::Redis(val) => val.master.send(msg).await?,
// };
// Ok(())
// }
}
impl Data {
#[cfg(not(tarpaulin_include))]
pub async fn new() -> Self {
pub async fn new() -> Arc<Self> {
let db = PgPoolOptions::new()
.max_connections(SETTINGS.database.pool)
.connect(&SETTINGS.database.url)
@@ -52,20 +108,46 @@ impl Data {
.build()
.unwrap();
let master = Master::new(SETTINGS.pow.gc).start();
let cache = HashCache::default().start();
let data = match &SETTINGS.redis {
Some(val) => {
let master = RedisMaster::new(RedisConfig::Single(val.url.clone()))
.await
.unwrap()
.start();
let cache = RedisCache::new(RedisConfig::Single(val.url.clone()))
.await
.unwrap()
.start();
let captcha = Self::new_system(master, cache);
Data {
creds,
db,
captcha: SystemGroup::Redis(captcha),
}
}
None => {
let master = EmbeddedMaster::new(SETTINGS.pow.gc).start();
let cache = HashCache::default().start();
let captcha = Self::new_system(master, cache);
Data {
creds,
db,
captcha: SystemGroup::Embedded(captcha),
}
}
};
Arc::new(data)
}
fn new_system<A: Save, B: MasterTrait>(m: Addr<B>, c: Addr<A>) -> System<A, B> {
let pow = PoWConfigBuilder::default()
.salt(SETTINGS.pow.salt.clone())
.build()
.unwrap();
let captcha = SystemBuilder::default()
.master(master)
.cache(cache)
.pow(pow)
.build()
.unwrap();
Data { creds, db, captcha }
SystemBuilder::default().pow(pow).cache(c).master(m).build()
}
}