mirror of
https://github.com/mCaptcha/mCaptcha.git
synced 2026-02-11 10:05:41 +00:00
Fixes #8
```
$ cargo test
<--- snip --->
thread panicked while panicking. aborting.
Running unittests (target/debug/deps/tests_migrate-7d90f83f506b1b25)
```
gdb revealed that demo::demo_account_works receives a SIGKILL due to a
failed test. No idea why it didn't fail the usual way. The part where
the test fails hits an endpoint with the wrong datatype payload, it
should have failed with a 404 when the status was asserted but it
didn't. Fixing that fixed #8.
Additionally, all demo user functionality was restructured to include an
abort functionality, which can be used to kill the loop that deletes and
creates demo user throughout the runtime of the app.
This commit is contained in:
@@ -7,7 +7,7 @@ repository = "https://github.com/mCaptcha/mCaptcha"
|
|||||||
documentation = "https://mcaptcha.org/docs/"
|
documentation = "https://mcaptcha.org/docs/"
|
||||||
license = "AGPLv3 or later version"
|
license = "AGPLv3 or later version"
|
||||||
authors = ["realaravinth <realaravinth@batsense.net>"]
|
authors = ["realaravinth <realaravinth@batsense.net>"]
|
||||||
edition = "2018"
|
edition = "2021"
|
||||||
default-run = "mcaptcha"
|
default-run = "mcaptcha"
|
||||||
build = "build.rs"
|
build = "build.rs"
|
||||||
|
|
||||||
|
|||||||
56
src/demo.rs
56
src/demo.rs
@@ -15,9 +15,11 @@
|
|||||||
* 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::time::Duration;
|
use std::time::Duration;
|
||||||
|
//use std::sync::atomicBool
|
||||||
|
|
||||||
use actix::clock::sleep;
|
use actix::clock::sleep;
|
||||||
use actix::spawn;
|
use actix::spawn;
|
||||||
|
use tokio::task::JoinHandle;
|
||||||
|
|
||||||
use crate::api::v1::account::delete::runners::delete_user;
|
use crate::api::v1::account::delete::runners::delete_user;
|
||||||
use crate::api::v1::account::{username::runners::username_exists, AccountCheckPayload};
|
use crate::api::v1::account::{username::runners::username_exists, AccountCheckPayload};
|
||||||
@@ -31,13 +33,36 @@ pub const DEMO_USER: &str = "aaronsw";
|
|||||||
/// Demo password
|
/// Demo password
|
||||||
pub const DEMO_PASSWORD: &str = "password";
|
pub const DEMO_PASSWORD: &str = "password";
|
||||||
|
|
||||||
|
pub struct DemoUser {
|
||||||
|
data: AppData,
|
||||||
|
duration: Duration,
|
||||||
|
handle: JoinHandle<()>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DemoUser {
|
||||||
|
pub async fn spawn(data: AppData, duration: Duration) -> ServiceResult<Self> {
|
||||||
|
let handle = Self::run(data.clone(), duration.clone()).await?;
|
||||||
|
let d = Self {
|
||||||
|
data,
|
||||||
|
duration,
|
||||||
|
handle,
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(d)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub fn abort(&self) {
|
||||||
|
self.handle.abort();
|
||||||
|
}
|
||||||
|
|
||||||
/// register demo user runner
|
/// register demo user runner
|
||||||
async fn register_demo_user(data: &AppData) -> ServiceResult<()> {
|
async fn register_demo_user(data: &AppData) -> ServiceResult<()> {
|
||||||
let user_exists_payload = AccountCheckPayload {
|
let user_exists_payload = AccountCheckPayload {
|
||||||
val: DEMO_USER.into(),
|
val: DEMO_USER.into(),
|
||||||
};
|
};
|
||||||
|
|
||||||
if !username_exists(&user_exists_payload, data).await?.exists {
|
if !username_exists(&user_exists_payload, &data).await?.exists {
|
||||||
let register_payload = Register {
|
let register_payload = Register {
|
||||||
username: DEMO_USER.into(),
|
username: DEMO_USER.into(),
|
||||||
password: DEMO_PASSWORD.into(),
|
password: DEMO_PASSWORD.into(),
|
||||||
@@ -46,7 +71,7 @@ async fn register_demo_user(data: &AppData) -> ServiceResult<()> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
log::info!("Registering demo user");
|
log::info!("Registering demo user");
|
||||||
match register_runner(®ister_payload, data).await {
|
match register_runner(®ister_payload, &data).await {
|
||||||
Err(ServiceError::UsernameTaken) | Ok(_) => Ok(()),
|
Err(ServiceError::UsernameTaken) | Ok(_) => Ok(()),
|
||||||
Err(e) => Err(e),
|
Err(e) => Err(e),
|
||||||
}
|
}
|
||||||
@@ -57,26 +82,30 @@ async fn register_demo_user(data: &AppData) -> ServiceResult<()> {
|
|||||||
|
|
||||||
async fn delete_demo_user(data: &AppData) -> ServiceResult<()> {
|
async fn delete_demo_user(data: &AppData) -> ServiceResult<()> {
|
||||||
log::info!("Deleting demo user");
|
log::info!("Deleting demo user");
|
||||||
delete_user(DEMO_USER, data).await?;
|
delete_user(DEMO_USER, &data).await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn run(data: AppData, duration: Duration) -> ServiceResult<()> {
|
pub async fn run(
|
||||||
register_demo_user(&data).await?;
|
data: AppData,
|
||||||
|
duration: Duration,
|
||||||
|
) -> ServiceResult<JoinHandle<()>> {
|
||||||
|
Self::register_demo_user(&data).await?;
|
||||||
|
|
||||||
let fut = async move {
|
let fut = async move {
|
||||||
loop {
|
loop {
|
||||||
sleep(duration).await;
|
sleep(duration).await;
|
||||||
if let Err(e) = delete_demo_user(&data).await {
|
if let Err(e) = Self::delete_demo_user(&data).await {
|
||||||
log::error!("Error while deleting demo user: {:?}", e);
|
log::error!("Error while deleting demo user: {:?}", e);
|
||||||
}
|
}
|
||||||
if let Err(e) = register_demo_user(&data).await {
|
if let Err(e) = Self::register_demo_user(&data).await {
|
||||||
log::error!("Error while registering demo user: {:?}", e);
|
log::error!("Error while registering demo user: {:?}", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
spawn(fut);
|
let handle = spawn(fut);
|
||||||
Ok(())
|
Ok(handle)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
@@ -100,7 +129,7 @@ mod tests {
|
|||||||
let duration = Duration::from_secs(DURATION);
|
let duration = Duration::from_secs(DURATION);
|
||||||
|
|
||||||
// register works
|
// register works
|
||||||
let _ = register_demo_user(&data).await.unwrap();
|
let _ = DemoUser::register_demo_user(&data).await.unwrap();
|
||||||
let payload = AccountCheckPayload {
|
let payload = AccountCheckPayload {
|
||||||
val: DEMO_USER.into(),
|
val: DEMO_USER.into(),
|
||||||
};
|
};
|
||||||
@@ -108,11 +137,11 @@ mod tests {
|
|||||||
signin(DEMO_USER, DEMO_PASSWORD).await;
|
signin(DEMO_USER, DEMO_PASSWORD).await;
|
||||||
|
|
||||||
// deletion works
|
// deletion works
|
||||||
assert!(super::delete_demo_user(&data).await.is_ok());
|
assert!(DemoUser::delete_demo_user(&data).await.is_ok());
|
||||||
assert!(!username_exists(&payload, &data).await.unwrap().exists);
|
assert!(!username_exists(&payload, &data).await.unwrap().exists);
|
||||||
|
|
||||||
// test the runner
|
// test the runner
|
||||||
run(data, duration).await.unwrap();
|
let user = DemoUser::spawn(data, duration).await.unwrap();
|
||||||
let (data_inner, _, signin_resp, token_key) =
|
let (data_inner, _, signin_resp, token_key) =
|
||||||
add_levels_util(DEMO_USER, DEMO_PASSWORD).await;
|
add_levels_util(DEMO_USER, DEMO_PASSWORD).await;
|
||||||
let cookies = get_cookie!(signin_resp);
|
let cookies = get_cookie!(signin_resp);
|
||||||
@@ -133,7 +162,7 @@ mod tests {
|
|||||||
|
|
||||||
let resp = test::call_service(
|
let resp = test::call_service(
|
||||||
&app,
|
&app,
|
||||||
post_request!(&token_key, crate::V1_API_ROUTES.captcha.create)
|
post_request!(&token_key, crate::V1_API_ROUTES.captcha.get)
|
||||||
.cookie(cookies)
|
.cookie(cookies)
|
||||||
.to_request(),
|
.to_request(),
|
||||||
)
|
)
|
||||||
@@ -141,5 +170,6 @@ mod tests {
|
|||||||
assert_eq!(resp.status(), StatusCode::OK);
|
assert_eq!(resp.status(), StatusCode::OK);
|
||||||
let res_levels: Vec<Level> = test::read_body_json(resp).await;
|
let res_levels: Vec<Level> = test::read_body_json(resp).await;
|
||||||
assert!(res_levels.is_empty());
|
assert!(res_levels.is_empty());
|
||||||
|
user.abort();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
16
src/main.rs
16
src/main.rs
@@ -54,6 +54,7 @@ pub use settings::Settings;
|
|||||||
use static_assets::FileMap;
|
use static_assets::FileMap;
|
||||||
pub use widget::WIDGET_ROUTES;
|
pub use widget::WIDGET_ROUTES;
|
||||||
|
|
||||||
|
use crate::demo::DemoUser;
|
||||||
pub use crate::middleware::auth::CheckLogin;
|
pub use crate::middleware::auth::CheckLogin;
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
@@ -114,10 +115,14 @@ async fn main() -> std::io::Result<()> {
|
|||||||
sqlx::migrate!("./migrations/").run(&data.db).await.unwrap();
|
sqlx::migrate!("./migrations/").run(&data.db).await.unwrap();
|
||||||
let data = actix_web::web::Data::new(data);
|
let data = actix_web::web::Data::new(data);
|
||||||
|
|
||||||
|
let mut demo_user: Option<DemoUser> = None;
|
||||||
|
|
||||||
if SETTINGS.allow_demo && SETTINGS.allow_registration {
|
if SETTINGS.allow_demo && SETTINGS.allow_registration {
|
||||||
demo::run(data.clone(), Duration::from_secs(60 * 30))
|
demo_user = Some(
|
||||||
|
DemoUser::spawn(data.clone(), Duration::from_secs(60 * 30))
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap(),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
println!("Starting server on: http://{}", SETTINGS.server.get_ip());
|
println!("Starting server on: http://{}", SETTINGS.server.get_ip());
|
||||||
@@ -141,7 +146,12 @@ async fn main() -> std::io::Result<()> {
|
|||||||
.bind(SETTINGS.server.get_ip())
|
.bind(SETTINGS.server.get_ip())
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.run()
|
.run()
|
||||||
.await
|
.await?;
|
||||||
|
|
||||||
|
if let Some(demo_user) = demo_user {
|
||||||
|
demo_user.abort();
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(tarpaulin_include))]
|
#[cfg(not(tarpaulin_include))]
|
||||||
|
|||||||
Reference in New Issue
Block a user