diff --git a/src/api/v1/account/delete.rs b/src/api/v1/account/delete.rs
index edc2d1cd..69005e4d 100644
--- a/src/api/v1/account/delete.rs
+++ b/src/api/v1/account/delete.rs
@@ -47,9 +47,7 @@ async fn delete_account(
match rec {
Ok(s) => {
if Config::verify(&s.password, &payload.password)? {
- sqlx::query!("DELETE FROM mcaptcha_users WHERE name = ($1)", &username)
- .execute(&data.db)
- .await?;
+ runners::delete_user(&username, &data).await?;
id.forget();
Ok(HttpResponse::Ok())
} else {
@@ -61,6 +59,18 @@ async fn delete_account(
}
}
+pub mod runners {
+
+ use super::*;
+
+ pub async fn delete_user(name: &str, data: &AppData) -> ServiceResult<()> {
+ sqlx::query!("DELETE FROM mcaptcha_users WHERE name = ($1)", name,)
+ .execute(&data.db)
+ .await?;
+ Ok(())
+ }
+}
+
pub fn services(cfg: &mut actix_web::web::ServiceConfig) {
cfg.service(delete_account);
}
diff --git a/src/api/v1/account/password.rs b/src/api/v1/account/password.rs
index d97f14b9..cda0f7e1 100644
--- a/src/api/v1/account/password.rs
+++ b/src/api/v1/account/password.rs
@@ -114,7 +114,7 @@ pub fn services(cfg: &mut actix_web::web::ServiceConfig) {
mod tests {
use super::*;
- use actix_web::http::{header, StatusCode};
+ use actix_web::http::StatusCode;
use actix_web::test;
use crate::api::v1::ROUTES;
diff --git a/src/api/v1/account/test.rs b/src/api/v1/account/test.rs
index 38a137cd..2cd4be2f 100644
--- a/src/api/v1/account/test.rs
+++ b/src/api/v1/account/test.rs
@@ -15,7 +15,7 @@
* along with this program. If not, see .
*/
-use actix_web::http::{header, StatusCode};
+use actix_web::http::StatusCode;
use actix_web::test;
use super::email::*;
diff --git a/src/api/v1/auth.rs b/src/api/v1/auth.rs
index 3bcd47fb..56eaf66e 100644
--- a/src/api/v1/auth.rs
+++ b/src/api/v1/auth.rs
@@ -24,11 +24,6 @@ use super::mcaptcha::get_random;
use crate::errors::*;
use crate::AppData;
-/// Demo username
-pub const DEMO_USER: &str = "aaronsw";
-/// Demo password
-pub const DEMO_PASSWORD: &str = "password";
-
pub mod routes {
pub struct Auth {
pub logout: &'static str,
@@ -199,21 +194,6 @@ pub mod runners {
}
Ok(())
}
-
- /// register demo user runner
- pub async fn register_demo_user(data: &AppData) -> ServiceResult<()> {
- let payload = runners::Register {
- username: DEMO_USER.into(),
- password: DEMO_PASSWORD.into(),
- confirm_password: DEMO_PASSWORD.into(),
- email: None,
- };
-
- match register_runner(&payload, data).await {
- Err(ServiceError::UsernameTaken) | Ok(_) => Ok(()),
- Err(e) => Err(e),
- }
- }
}
pub fn services(cfg: &mut web::ServiceConfig) {
diff --git a/src/api/v1/mcaptcha/captcha.rs b/src/api/v1/mcaptcha/captcha.rs
index d2853c68..e3e8be69 100644
--- a/src/api/v1/mcaptcha/captcha.rs
+++ b/src/api/v1/mcaptcha/captcha.rs
@@ -276,7 +276,7 @@ async fn get_stats(
#[cfg(test)]
mod tests {
- use actix_web::http::{header, StatusCode};
+ use actix_web::http::StatusCode;
use actix_web::test;
use super::*;
diff --git a/src/api/v1/mcaptcha/duration.rs b/src/api/v1/mcaptcha/duration.rs
index d0fabcd3..310ef015 100644
--- a/src/api/v1/mcaptcha/duration.rs
+++ b/src/api/v1/mcaptcha/duration.rs
@@ -130,7 +130,7 @@ pub fn services(cfg: &mut web::ServiceConfig) {
#[cfg(test)]
mod tests {
- use actix_web::http::{header, StatusCode};
+ use actix_web::http::StatusCode;
use actix_web::test;
use super::*;
diff --git a/src/api/v1/mcaptcha/levels.rs b/src/api/v1/mcaptcha/levels.rs
index 31b4f333..6b4e1be4 100644
--- a/src/api/v1/mcaptcha/levels.rs
+++ b/src/api/v1/mcaptcha/levels.rs
@@ -241,7 +241,7 @@ async fn get_levels_util(
#[cfg(test)]
mod tests {
- use actix_web::http::{header, StatusCode};
+ use actix_web::http::StatusCode;
use actix_web::test;
use super::*;
diff --git a/src/api/v1/mcaptcha/mod.rs b/src/api/v1/mcaptcha/mod.rs
index 870f668a..6c649565 100644
--- a/src/api/v1/mcaptcha/mod.rs
+++ b/src/api/v1/mcaptcha/mod.rs
@@ -1,19 +1,19 @@
/*
-* Copyright (C) 2021 Aravinth Manivannan
-*
-* This program is free software: you can redistribute it and/or modify
-* it under the terms of the GNU Affero General Public License as
-* published by the Free Software Foundation, either version 3 of the
-* License, or (at your option) any later version.
-*
-* This program is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-* GNU Affero General Public License for more details.
-*
-* You should have received a copy of the GNU Affero General Public License
-* along with this program. If not, see .
-*/
+ * Copyright (C) 2021 Aravinth Manivannan
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
pub mod captcha;
pub mod duration;
diff --git a/src/api/v1/notifications/add.rs b/src/api/v1/notifications/add.rs
index b5d8c754..bece1080 100644
--- a/src/api/v1/notifications/add.rs
+++ b/src/api/v1/notifications/add.rs
@@ -61,7 +61,7 @@ pub async fn add_notification(
#[cfg(test)]
mod tests {
- use actix_web::http::{header, StatusCode};
+ use actix_web::http::StatusCode;
use actix_web::test;
use super::*;
diff --git a/src/api/v1/notifications/get.rs b/src/api/v1/notifications/get.rs
index 3dbad32f..ac9f416f 100644
--- a/src/api/v1/notifications/get.rs
+++ b/src/api/v1/notifications/get.rs
@@ -98,7 +98,7 @@ pub mod runner {
#[cfg(test)]
mod tests {
- use actix_web::http::{header, StatusCode};
+ use actix_web::http::StatusCode;
use actix_web::test;
use super::*;
diff --git a/src/api/v1/notifications/mark_read.rs b/src/api/v1/notifications/mark_read.rs
index 169b0cfb..73aca4b7 100644
--- a/src/api/v1/notifications/mark_read.rs
+++ b/src/api/v1/notifications/mark_read.rs
@@ -63,7 +63,7 @@ pub async fn mark_read(
#[cfg(test)]
mod tests {
- use actix_web::http::{header, StatusCode};
+ use actix_web::http::StatusCode;
use actix_web::test;
use super::*;
diff --git a/src/api/v1/pow/get_config.rs b/src/api/v1/pow/get_config.rs
index b5be3942..6f43eee3 100644
--- a/src/api/v1/pow/get_config.rs
+++ b/src/api/v1/pow/get_config.rs
@@ -152,7 +152,7 @@ async fn init_mcaptcha(data: &AppData, key: &str) -> ServiceResult<()> {
#[cfg(test)]
mod tests {
- use actix_web::http::{header, StatusCode};
+ use actix_web::http::StatusCode;
use actix_web::test;
use libmcaptcha::pow::PoWConfig;
diff --git a/src/api/v1/pow/verify_pow.rs b/src/api/v1/pow/verify_pow.rs
index 5f373114..652b21f2 100644
--- a/src/api/v1/pow/verify_pow.rs
+++ b/src/api/v1/pow/verify_pow.rs
@@ -52,7 +52,7 @@ pub async fn verify_pow(
#[cfg(test)]
mod tests {
- use actix_web::http::{header, StatusCode};
+ use actix_web::http::StatusCode;
use actix_web::test;
use libmcaptcha::pow::PoWConfig;
diff --git a/src/api/v1/pow/verify_token.rs b/src/api/v1/pow/verify_token.rs
index 57a6c5c7..66c0ab58 100644
--- a/src/api/v1/pow/verify_token.rs
+++ b/src/api/v1/pow/verify_token.rs
@@ -53,7 +53,7 @@ pub async fn validate_captcha_token(
#[cfg(test)]
mod tests {
- use actix_web::http::{header, StatusCode};
+ use actix_web::http::StatusCode;
use actix_web::test;
use libmcaptcha::pow::PoWConfig;
use libmcaptcha::pow::Work;
diff --git a/src/api/v1/tests/auth.rs b/src/api/v1/tests/auth.rs
index e28e7042..6f5733c1 100644
--- a/src/api/v1/tests/auth.rs
+++ b/src/api/v1/tests/auth.rs
@@ -18,11 +18,7 @@
use actix_web::http::{header, StatusCode};
use actix_web::test;
-use crate::api::v1::account::{username::runners::username_exists, AccountCheckPayload};
-use crate::api::v1::auth::{
- runners::{register_demo_user, Login, Register},
- DEMO_PASSWORD, DEMO_USER,
-};
+use crate::api::v1::auth::runners::{Login, Register};
use crate::api::v1::ROUTES;
use crate::data::Data;
use crate::errors::*;
@@ -167,17 +163,3 @@ async fn serverside_password_validation_works() {
let txt: ErrorToResponse = test::read_body_json(resp).await;
assert_eq!(txt.error, format!("{}", ServiceError::PasswordsDontMatch));
}
-
-#[actix_rt::test]
-async fn demo_account() {
- let data = AppData::new(Data::new().await);
- let _ = register_demo_user(&data).await.unwrap();
-
- let payload = AccountCheckPayload {
- val: DEMO_USER.into(),
- };
-
- assert!(username_exists(&payload, &data).await.unwrap().exists);
-
- signin(DEMO_USER, DEMO_PASSWORD).await;
-}
diff --git a/src/demo.rs b/src/demo.rs
new file mode 100644
index 00000000..3c1d4a89
--- /dev/null
+++ b/src/demo.rs
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2021 Aravinth Manivannan
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+use std::time::Duration;
+
+use actix::clock::sleep;
+use actix::spawn;
+
+use crate::api::v1::account::delete::runners::delete_user;
+use crate::api::v1::auth::runners::{register_runner, Register};
+use crate::*;
+
+use errors::*;
+
+/// Demo username
+pub const DEMO_USER: &str = "aaronsw";
+/// Demo password
+pub const DEMO_PASSWORD: &str = "password";
+
+/// register demo user runner
+async fn register_demo_user(data: &AppData) -> ServiceResult<()> {
+ let payload = Register {
+ username: DEMO_USER.into(),
+ password: DEMO_PASSWORD.into(),
+ confirm_password: DEMO_PASSWORD.into(),
+ email: None,
+ };
+
+ log::info!("Registering demo user");
+ match register_runner(&payload, data).await {
+ Err(ServiceError::UsernameTaken) | Ok(_) => Ok(()),
+ Err(e) => Err(e),
+ }
+}
+
+async fn delete_demo_user(data: &AppData) -> ServiceResult<()> {
+ log::info!("Deleting demo user");
+ delete_user(DEMO_USER, data).await?;
+ Ok(())
+}
+
+pub async fn run(data: AppData, duration: Duration) -> ServiceResult<()> {
+ register_demo_user(&data).await?;
+ let fut = async move {
+ loop {
+ sleep(duration).await;
+ if let Err(e) = delete_demo_user(&data).await {
+ log::error!("Error while deleting demo user: {:?}", e);
+ }
+ if let Err(e) = register_demo_user(&data).await {
+ log::error!("Error while registering demo user: {:?}", e);
+ }
+ }
+ };
+ spawn(fut);
+ Ok(())
+}
+
+#[cfg(test)]
+mod tests {
+
+ use actix_web::test;
+ use libmcaptcha::defense::Level;
+
+ use super::*;
+ use crate::api::v1::account::{
+ username::runners::username_exists, AccountCheckPayload,
+ };
+ use crate::tests::*;
+
+ const DURATION: u64 = 5;
+
+ #[actix_rt::test]
+ async fn demo_account_works() {
+ {
+ let data = Data::new().await;
+ crate::tests::delete_user(DEMO_USER, &data).await;
+ }
+ let data = AppData::new(Data::new().await);
+ let duration = Duration::from_secs(DURATION);
+
+ // register works
+ let _ = register_demo_user(&data).await.unwrap();
+ let payload = AccountCheckPayload {
+ val: DEMO_USER.into(),
+ };
+ assert!(username_exists(&payload, &data).await.unwrap().exists);
+ signin(DEMO_USER, DEMO_PASSWORD).await;
+
+ // deletion works
+ assert!(super::delete_demo_user(&data).await.is_ok());
+ assert!(!username_exists(&payload, &data).await.unwrap().exists);
+
+ // test the runner
+ run(data, duration).await.unwrap();
+ let (data_inner, _, signin_resp, token_key) =
+ add_levels_util(DEMO_USER, DEMO_PASSWORD).await;
+ let cookies = get_cookie!(signin_resp);
+ let app = get_app!(data_inner).await;
+
+ let resp = test::call_service(
+ &app,
+ post_request!(&token_key, crate::V1_API_ROUTES.levels.get)
+ .cookie(cookies.clone())
+ .to_request(),
+ )
+ .await;
+ assert_eq!(resp.status(), StatusCode::OK);
+ let res_levels: Vec = test::read_body_json(resp).await;
+ assert!(!res_levels.is_empty());
+
+ sleep(Duration::from_secs(DURATION * 2)).await;
+
+ let resp = test::call_service(
+ &app,
+ post_request!(&token_key, crate::V1_API_ROUTES.levels.get)
+ .cookie(cookies)
+ .to_request(),
+ )
+ .await;
+ assert_eq!(resp.status(), StatusCode::OK);
+ let res_levels: Vec = test::read_body_json(resp).await;
+ assert!(res_levels.is_empty());
+ }
+}
diff --git a/src/main.rs b/src/main.rs
index 8a0ba96c..25d77df5 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -28,6 +28,7 @@ use log::info;
mod api;
mod data;
mod date;
+mod demo;
mod docs;
mod email;
mod errors;
@@ -100,6 +101,8 @@ pub type AppData = actix_web::web::Data>;
#[cfg(not(tarpaulin_include))]
#[actix_web::main]
async fn main() -> std::io::Result<()> {
+ use std::time::Duration;
+
use api::v1;
env::set_var("RUST_LOG", "info");
@@ -114,6 +117,12 @@ async fn main() -> std::io::Result<()> {
sqlx::migrate!("./migrations/").run(&data.db).await.unwrap();
let data = actix_web::web::Data::new(data);
+ if SETTINGS.allow_demo && SETTINGS.allow_registration {
+ demo::run(data.clone(), Duration::from_secs(60 * 30))
+ .await
+ .unwrap();
+ }
+
println!("Starting server on: http://{}", SETTINGS.server.get_ip());
HttpServer::new(move || {
diff --git a/src/tests/mod.rs b/src/tests/mod.rs
index 5d0ba3e1..49b9717c 100644
--- a/src/tests/mod.rs
+++ b/src/tests/mod.rs
@@ -2,9 +2,7 @@ use std::sync::Arc;
use actix_web::test;
use actix_web::{
- dev::ServiceResponse,
- error::ResponseError,
- http::{header, StatusCode},
+ dev::ServiceResponse, error::ResponseError, http::StatusCode,
middleware as actix_middleware,
};
use libmcaptcha::defense::Level;
@@ -44,7 +42,7 @@ macro_rules! post_request {
($serializable:expr, $uri:expr) => {
test::TestRequest::post()
.uri($uri)
- .insert_header((header::CONTENT_TYPE, "application/json"))
+ .insert_header((actix_web::http::header::CONTENT_TYPE, "application/json"))
.set_payload(serde_json::to_string($serializable).unwrap())
};
}