feat: migrate fetch captcha config to use db_*

This commit is contained in:
realaravinth 2022-05-27 18:16:47 +05:30
parent 3a535c04a6
commit cd72ae6ffe
No known key found for this signature in database
GPG Key ID: AD9F0F08E855ED88
10 changed files with 45 additions and 113 deletions

View File

@ -14,7 +14,6 @@
* You should have received a copy of the GNU Affero General Public License * 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/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
use std::env;
use std::process::Command; use std::process::Command;
use sqlx::types::time::OffsetDateTime; use sqlx::types::time::OffsetDateTime;

View File

@ -149,8 +149,6 @@ impl SystemGroup {
/// App data /// App data
pub struct Data { pub struct Data {
/// databse pool
pub db: PgPool,
/// database ops defined by db crates /// database ops defined by db crates
pub dblib: Box<dyn MCDatabase>, pub dblib: Box<dyn MCDatabase>,
/// credential management configuration /// credential management configuration
@ -188,11 +186,11 @@ impl Data {
log::info!("Initialized credential manager"); log::info!("Initialized credential manager");
}); });
let db = PgPoolOptions::new() // let db = PgPoolOptions::new()
.max_connections(s.database.pool) // .max_connections(s.database.pool)
.connect(&s.database.url) // .connect(&s.database.url)
.await // .await
.expect("Unable to form database pool"); // .expect("Unable to form database pool");
let pool = s.database.pool; let pool = s.database.pool;
let pool_options = PgPoolOptions::new().max_connections(pool); let pool_options = PgPoolOptions::new().max_connections(pool);
@ -211,7 +209,7 @@ impl Data {
let data = Data { let data = Data {
creds, creds,
db, //db,
dblib: Box::new(dblib), dblib: Box::new(dblib),
captcha: SystemGroup::new(s).await, captcha: SystemGroup::new(s).await,
mailer: Self::get_mailer(s), mailer: Self::get_mailer(s),

View File

@ -240,20 +240,20 @@ impl From<CaptchaError> for ServiceError {
} }
} }
#[cfg(not(tarpaulin_include))] //#[cfg(not(tarpaulin_include))]
impl From<sqlx::Error> for ServiceError { //impl From<sqlx::Error> for ServiceError {
#[cfg(not(tarpaulin_include))] // #[cfg(not(tarpaulin_include))]
fn from(e: sqlx::Error) -> Self { // fn from(e: sqlx::Error) -> Self {
use sqlx::error::Error; // use sqlx::error::Error;
use std::borrow::Cow; // use std::borrow::Cow;
if let Error::Database(err) = e { // if let Error::Database(err) = e {
if err.code() == Some(Cow::from("23505")) { // if err.code() == Some(Cow::from("23505")) {
return ServiceError::UsernameTaken; // return ServiceError::UsernameTaken;
} // }
} // }
ServiceError::InternalServerError // ServiceError::InternalServerError
} // }
} //}
#[cfg(not(tarpaulin_include))] #[cfg(not(tarpaulin_include))]
impl From<SmtpError> for ServiceError { impl From<SmtpError> for ServiceError {

View File

@ -23,18 +23,19 @@ mod notifications;
mod settings; mod settings;
pub mod sitekey; pub mod sitekey;
use db_core::Captcha;
use crate::errors::PageResult; use crate::errors::PageResult;
use crate::AppData; use crate::AppData;
use sitekey::list::{get_list_sitekeys, SiteKeys};
#[derive(TemplateOnce, Clone)] #[derive(TemplateOnce, Clone)]
#[template(path = "panel/index.html")] #[template(path = "panel/index.html")]
pub struct IndexPage { pub struct IndexPage {
sitekeys: SiteKeys, sitekeys: Vec<Captcha>,
} }
impl IndexPage { impl IndexPage {
fn new(sitekeys: SiteKeys) -> Self { fn new(sitekeys: Vec<Captcha>) -> Self {
IndexPage { sitekeys } IndexPage { sitekeys }
} }
} }
@ -46,7 +47,8 @@ const PAGE: &str = "Dashboard";
wrap = "crate::pages::get_middleware()" wrap = "crate::pages::get_middleware()"
)] )]
async fn panel(data: AppData, id: Identity) -> PageResult<impl Responder> { async fn panel(data: AppData, id: Identity) -> PageResult<impl Responder> {
let sitekeys = get_list_sitekeys(&data, &id).await?; let username = id.identity().unwrap();
let sitekeys = data.dblib.get_all_user_captchas(&username).await?;
let body = IndexPage::new(sitekeys).render_once().unwrap(); let body = IndexPage::new(sitekeys).render_once().unwrap();
Ok(HttpResponse::Ok() Ok(HttpResponse::Ok()
.content_type("text/html; charset=utf-8") .content_type("text/html; charset=utf-8")

View File

@ -21,7 +21,7 @@ use sailfish::TemplateOnce;
use sqlx::types::time::OffsetDateTime; use sqlx::types::time::OffsetDateTime;
use crate::date::Date; use crate::date::Date;
use crate::errors::{PageError, PageResult, ServiceError}; use crate::errors::PageResult;
use crate::AppData; use crate::AppData;
#[derive(TemplateOnce)] #[derive(TemplateOnce)]

View File

@ -19,6 +19,7 @@ use actix_web::{http, web, HttpResponse, Responder};
use sailfish::TemplateOnce; use sailfish::TemplateOnce;
use db_core::errors::DBError; use db_core::errors::DBError;
use db_core::Captcha;
use libmcaptcha::defense::Level; use libmcaptcha::defense::Level;
use crate::api::v1::mcaptcha::easy::TrafficPatternRequest; use crate::api::v1::mcaptcha::easy::TrafficPatternRequest;
@ -27,19 +28,6 @@ use crate::AppData;
const PAGE: &str = "Edit Sitekey"; const PAGE: &str = "Edit Sitekey";
#[derive(Clone)]
struct McaptchaConfig {
config_id: i32,
duration: i32,
name: String,
}
//#[derive(Clone)]
//struct Level {
// difficulty_factor: i32,
// visitor_threshold: i32,
//}
#[derive(TemplateOnce, Clone)] #[derive(TemplateOnce, Clone)]
#[template(path = "panel/sitekey/edit/advance.html")] #[template(path = "panel/sitekey/edit/advance.html")]
struct AdvanceEditPage { struct AdvanceEditPage {
@ -50,10 +38,10 @@ struct AdvanceEditPage {
} }
impl AdvanceEditPage { impl AdvanceEditPage {
fn new(config: McaptchaConfig, levels: Vec<Level>, key: String) -> Self { fn new(config: Captcha, levels: Vec<Level>, key: String) -> Self {
AdvanceEditPage { AdvanceEditPage {
duration: config.duration as u32, duration: config.duration as u32,
name: config.name, name: config.description,
levels, levels,
key, key,
} }
@ -73,17 +61,7 @@ pub async fn advance(
let username = id.identity().unwrap(); let username = id.identity().unwrap();
let key = path.into_inner(); let key = path.into_inner();
let config = sqlx::query_as!( let config = data.dblib.get_captcha_config(&username, &key).await?;
McaptchaConfig,
"SELECT config_id, duration, name from mcaptcha_config WHERE
key = $1 AND
user_id = (SELECT ID FROM mcaptcha_users WHERE name = $2) ",
&key,
&username,
)
.fetch_one(&data.db)
.await?;
let levels = data.dblib.get_captcha_levels(Some(&username), &key).await?; let levels = data.dblib.get_captcha_levels(Some(&username), &key).await?;
let body = AdvanceEditPage::new(config, levels, key) let body = AdvanceEditPage::new(config, levels, key)
@ -127,26 +105,12 @@ pub async fn easy(
match data.dblib.get_traffic_pattern(&username, &key).await { match data.dblib.get_traffic_pattern(&username, &key).await {
Ok(c) => { Ok(c) => {
struct Description { let config = data.dblib.get_captcha_config(&username, &key).await?;
name: String,
}
let description = sqlx::query_as!(
Description,
"SELECT name FROM mcaptcha_config
WHERE key = $1
AND user_id = (
SELECT user_id FROM mcaptcha_users WHERE NAME = $2)",
&key,
&username
)
.fetch_one(&data.db)
.await?;
let pattern = TrafficPatternRequest { let pattern = TrafficPatternRequest {
peak_sustainable_traffic: c.peak_sustainable_traffic as u32, peak_sustainable_traffic: c.peak_sustainable_traffic as u32,
avg_traffic: c.avg_traffic as u32, avg_traffic: c.avg_traffic as u32,
broke_my_site_traffic: c.broke_my_site_traffic.map(|n| n as u32), broke_my_site_traffic: c.broke_my_site_traffic.map(|n| n as u32),
description: description.name, description: config.description,
}; };
let page = EasyEditPage::new(key, pattern).render_once().unwrap(); let page = EasyEditPage::new(key, pattern).render_once().unwrap();

View File

@ -19,20 +19,21 @@ use actix_identity::Identity;
use actix_web::{HttpResponse, Responder}; use actix_web::{HttpResponse, Responder};
use sailfish::TemplateOnce; use sailfish::TemplateOnce;
use crate::api::v1::mcaptcha::create::MCaptchaDetails; use db_core::Captcha;
use crate::errors::*; use crate::errors::*;
use crate::AppData; use crate::AppData;
#[derive(TemplateOnce, Clone)] #[derive(TemplateOnce, Clone)]
#[template(path = "panel/sitekey/list/index.html")] #[template(path = "panel/sitekey/list/index.html")]
pub struct IndexPage { pub struct IndexPage {
sitekeys: SiteKeys, sitekeys: Vec<Captcha>,
} }
const PAGE: &str = "SiteKeys"; const PAGE: &str = "SiteKeys";
impl IndexPage { impl IndexPage {
fn new(sitekeys: SiteKeys) -> Self { fn new(sitekeys: Vec<Captcha>) -> Self {
IndexPage { sitekeys } IndexPage { sitekeys }
} }
} }
@ -43,29 +44,14 @@ impl IndexPage {
wrap = "crate::pages::get_middleware()" wrap = "crate::pages::get_middleware()"
)] )]
pub async fn list_sitekeys(data: AppData, id: Identity) -> PageResult<impl Responder> { pub async fn list_sitekeys(data: AppData, id: Identity) -> PageResult<impl Responder> {
let res = get_list_sitekeys(&data, &id).await?; let username = id.identity().unwrap();
let res = data.dblib.get_all_user_captchas(&username).await?;
let body = IndexPage::new(res).render_once().unwrap(); let body = IndexPage::new(res).render_once().unwrap();
Ok(HttpResponse::Ok() Ok(HttpResponse::Ok()
.content_type("text/html; charset=utf-8") .content_type("text/html; charset=utf-8")
.body(body)) .body(body))
} }
/// utility function to get a list of all sitekeys that a user owns
pub async fn get_list_sitekeys(data: &AppData, id: &Identity) -> PageResult<SiteKeys> {
let username = id.identity().unwrap();
let res = sqlx::query_as!(
MCaptchaDetails,
"SELECT key, name from mcaptcha_config WHERE
user_id = (SELECT ID FROM mcaptcha_users WHERE name = $1) ",
&username,
)
.fetch_all(&data.db)
.await?;
Ok(res)
}
pub type SiteKeys = Vec<MCaptchaDetails>;
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use actix_web::http::StatusCode; use actix_web::http::StatusCode;

View File

@ -19,6 +19,7 @@ use actix_identity::Identity;
use actix_web::{web, HttpResponse, Responder}; use actix_web::{web, HttpResponse, Responder};
use sailfish::TemplateOnce; use sailfish::TemplateOnce;
use db_core::Captcha;
use libmcaptcha::defense::Level; use libmcaptcha::defense::Level;
use crate::errors::*; use crate::errors::*;
@ -27,13 +28,6 @@ use crate::AppData;
const PAGE: &str = "SiteKeys"; const PAGE: &str = "SiteKeys";
#[derive(Clone)]
struct McaptchaConfig {
config_id: i32,
duration: i32,
name: String,
}
#[derive(TemplateOnce, Clone)] #[derive(TemplateOnce, Clone)]
#[template(path = "panel/sitekey/view/index.html")] #[template(path = "panel/sitekey/view/index.html")]
struct IndexPage { struct IndexPage {
@ -47,13 +41,13 @@ struct IndexPage {
impl IndexPage { impl IndexPage {
fn new( fn new(
stats: CaptchaStats, stats: CaptchaStats,
config: McaptchaConfig, config: Captcha,
levels: Vec<Level>, levels: Vec<Level>,
key: String, key: String,
) -> Self { ) -> Self {
IndexPage { IndexPage {
duration: config.duration as u32, duration: config.duration as u32,
name: config.name, name: config.description,
levels, levels,
key, key,
stats, stats,
@ -73,18 +67,7 @@ pub async fn view_sitekey(
) -> PageResult<impl Responder> { ) -> PageResult<impl Responder> {
let username = id.identity().unwrap(); let username = id.identity().unwrap();
let key = path.into_inner(); let key = path.into_inner();
let config = data.dblib.get_captcha_config(&username, &key).await?;
let config = sqlx::query_as!(
McaptchaConfig,
"SELECT config_id, duration, name from mcaptcha_config WHERE
key = $1 AND
user_id = (SELECT ID FROM mcaptcha_users WHERE name = $2) ",
&key,
&username,
)
.fetch_one(&data.db)
.await?;
let levels = data.dblib.get_captcha_levels(Some(&username), &key).await?; let levels = data.dblib.get_captcha_levels(Some(&username), &key).await?;
let stats = data.stats.fetch(&data, &username, &key).await?; let stats = data.stats.fetch(&data, &username, &key).await?;

View File

@ -29,7 +29,7 @@ include!("./navbar/index.html"); .>
href="/sitekey/<.= sitekey.key .>/" href="/sitekey/<.= sitekey.key .>/"
class="sitekey-list__sitekey-link" class="sitekey-list__sitekey-link"
> >
<.= sitekey.name .> <.= sitekey.description .>
</a> </a>
</td> </td>
<td class="sitekey-list__key"> <td class="sitekey-list__key">

View File

@ -31,7 +31,7 @@ include!("../../navbar/index.html"); .>
href="/sitekey/<.= sitekey.key .>/" href="/sitekey/<.= sitekey.key .>/"
class="sitekey-list__sitekey-link" class="sitekey-list__sitekey-link"
> >
<.= sitekey.name .> <.= sitekey.description .>
</a> </a>
</td> </td>
<td class="sitekey-list__key"> <td class="sitekey-list__key">