1use std::time::Duration;
7use actix::clock::sleep;
10use actix::spawn;
11use tokio::sync::oneshot::{channel, error::TryRecvError, Receiver, Sender};
12use tokio::task::JoinHandle;
13
14use crate::api::v1::account::delete::runners::delete_user;
15use crate::api::v1::account::{username::runners::username_exists, AccountCheckPayload};
16use crate::api::v1::auth::runners::{register_runner, Register};
17use crate::*;
18
19use errors::*;
20
21pub const DEMO_USER: &str = "aaronsw";
23pub const DEMO_PASSWORD: &str = "password";
25
26pub struct DemoUser {
27 tx: Sender<()>,
28}
29
30impl DemoUser {
31 pub async fn spawn(
32 data: AppData,
33 duration: u32,
34 ) -> ServiceResult<(Self, JoinHandle<()>)> {
35 let (tx, rx) = channel();
36 let handle = Self::run(data, duration, rx).await?;
37 let d = Self { tx };
38
39 Ok((d, handle))
40 }
41
42 #[allow(dead_code)]
43 pub fn abort(mut self) {
44 self.tx.send(());
45 }
46
47 async fn register_demo_user(data: &AppData) -> ServiceResult<()> {
49 let user_exists_payload = AccountCheckPayload {
50 val: DEMO_USER.into(),
51 };
52
53 if !username_exists(&user_exists_payload, data).await?.exists {
54 let register_payload = Register {
55 username: DEMO_USER.into(),
56 password: DEMO_PASSWORD.into(),
57 confirm_password: DEMO_PASSWORD.into(),
58 email: None,
59 };
60
61 log::info!("Registering demo user");
62 match register_runner(®ister_payload, data).await {
63 Err(ServiceError::UsernameTaken) | Ok(_) => Ok(()),
64 Err(e) => Err(e),
65 }
66 } else {
67 Ok(())
68 }
69 }
70
71 async fn delete_demo_user(data: &AppData) -> ServiceResult<()> {
72 log::info!("Deleting demo user");
73 delete_user(DEMO_USER, data).await?;
74 Ok(())
75 }
76
77 pub async fn run(
78 data: AppData,
79 duration: u32,
80 mut rx: Receiver<()>,
81 ) -> ServiceResult<JoinHandle<()>> {
82 Self::register_demo_user(&data).await?;
83
84 fn can_run(rx: &mut Receiver<()>) -> bool {
85 match rx.try_recv() {
86 Err(TryRecvError::Empty) => true,
87 _ => false,
88 }
89 }
90
91 let mut exit = false;
92 let fut = async move {
93 loop {
94 if exit {
95 break;
96 }
97 for _ in 0..duration {
98 if can_run(&mut rx) {
99 sleep(Duration::new(1, 0)).await;
100 continue;
101 } else {
102 exit = true;
103 break;
104 }
105 }
106
107 if let Err(e) = Self::delete_demo_user(&data).await {
108 log::error!("Error while deleting demo user: {:?}", e);
109 }
110
111 if let Err(e) = Self::register_demo_user(&data).await {
112 log::error!("Error while registering demo user: {:?}", e);
113 }
114 }
115 };
116 let handle = spawn(fut);
117 Ok(handle)
118 }
119}
120
121#[cfg(test)]
122mod tests {
123
124 use actix_web::test;
125 use libmcaptcha::defense::Level;
126
127 use super::*;
128 use crate::tests::*;
129
130 const DURATION: u64 = 25;
131
132 #[actix_rt::test]
133 async fn demo_account_works_pg() {
134 let data = crate::tests::pg::get_data().await;
135 demo_account_works(data).await;
136 }
137
138 #[actix_rt::test]
139 async fn demo_account_works_maria() {
140 let data = crate::tests::maria::get_data().await;
141 demo_account_works(data).await;
142 }
143
144 async fn demo_account_works(data_inner: ArcData) {
145 let data_inner = &data_inner;
146 let data = AppData::new(data_inner.clone());
147 crate::tests::delete_user(data_inner, DEMO_USER).await;
148 let duration = Duration::from_secs(DURATION);
149
150 DemoUser::register_demo_user(&data).await.unwrap();
152 let payload = AccountCheckPayload {
153 val: DEMO_USER.into(),
154 };
155 assert!(username_exists(&payload, &data).await.unwrap().exists);
156 signin(data_inner, DEMO_USER, DEMO_PASSWORD).await;
157
158 assert!(DemoUser::delete_demo_user(&data).await.is_ok());
160 assert!(!username_exists(&payload, &data).await.unwrap().exists);
161
162 let user = DemoUser::spawn(data, DURATION as u32).await.unwrap();
164 let (_, signin_resp, token_key) =
165 add_levels_util(data_inner, DEMO_USER, DEMO_PASSWORD).await;
166 let cookies = get_cookie!(signin_resp);
167 let app = get_app!(data_inner).await;
168
169 let resp = test::call_service(
170 &app,
171 post_request!(&token_key, crate::V1_API_ROUTES.captcha.get)
172 .cookie(cookies.clone())
173 .to_request(),
174 )
175 .await;
176 assert_eq!(resp.status(), StatusCode::OK);
177 let res_levels: Vec<Level> = test::read_body_json(resp).await;
178 assert!(!res_levels.is_empty());
179
180 sleep(Duration::from_secs(DURATION * 2)).await;
181
182 let resp = test::call_service(
183 &app,
184 post_request!(&token_key, crate::V1_API_ROUTES.captcha.get)
185 .cookie(cookies)
186 .to_request(),
187 )
188 .await;
189 assert_eq!(resp.status(), StatusCode::OK);
190 let res_levels: Vec<Level> = test::read_body_json(resp).await;
191 assert!(res_levels.is_empty());
192 user.0.abort();
193 user.1.await.unwrap();
194 }
195}