mirror of
https://github.com/mCaptcha/mCaptcha.git
synced 2025-06-08 07:06:40 +00:00
feat: migrate fetch captcha config to use db_*
This commit is contained in:
parent
3a535c04a6
commit
cd72ae6ffe
1
build.rs
1
build.rs
@ -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;
|
||||||
|
14
src/data.rs
14
src/data.rs
@ -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),
|
||||||
|
@ -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 {
|
||||||
|
@ -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")
|
||||||
|
@ -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)]
|
||||||
|
@ -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();
|
||||||
|
@ -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;
|
||||||
|
@ -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?;
|
||||||
|
|
||||||
|
@ -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">
|
||||||
|
@ -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">
|
||||||
|
Loading…
x
Reference in New Issue
Block a user