eeg_certs/backend/src/online_classroom/session.rs

139 lines
4.4 KiB
Rust
Raw Normal View History

use lazy_static::lazy_static;
use std::time::{SystemTime, UNIX_EPOCH};
use isahc::{cookies::CookieJar, prelude::*, Request};
use std::sync::RwLock;
struct CookieHold {
pub jar: CookieJar,
}
lazy_static! {
/// Stores a client with a persistent cookie store
static ref SESSION_COOKIE: RwLock<CookieHold> = RwLock::new(CookieHold { jar: CookieJar::new()});
/// Stores the last time a request was made, in seconds since UNIX epoch
static ref SESSION_TIME: RwLock<u64> = RwLock::new(0);
}
2023-09-30 16:16:20 +00:00
/// Makes a request to the online classroom, and returns the html string
2023-09-25 22:26:00 +00:00
pub async fn request(url: String) -> Result<String, String> {
let classroom_url = std::env::var("CLASSROOM_URL").expect("CLASSROOM_URL env var is not set!");
ensure_session().await?;
2023-09-30 16:16:20 +00:00
// Get the stored client
let jar = SESSION_COOKIE.read().unwrap().jar.clone();
2023-09-25 22:26:00 +00:00
let uri = format!("{}{}", classroom_url, url);
2023-09-30 16:16:20 +00:00
// Do the request
let response = Request::get(uri)
.cookie_jar(jar.clone())
.body(())
.or_else(|err| Err(format!("Error creating request: {:?}", err)))?
.send();
2023-09-25 22:26:00 +00:00
let mut response = match response {
2023-09-25 22:26:00 +00:00
Ok(r) => r,
2023-09-30 16:16:20 +00:00
Err(err) => return Err(format!("Error sending request: {:?}", err)),
2023-09-25 22:26:00 +00:00
};
match response.text() {
2023-09-25 22:26:00 +00:00
Ok(t) => Ok(t),
2023-09-30 16:16:20 +00:00
Err(err) => Err(format!("Error getting text from response: {:?}", err)),
2023-09-25 22:26:00 +00:00
}
}
2023-10-04 12:06:58 +00:00
/// Handles request for creating a user.
///
2023-10-04 12:06:58 +00:00
/// Returns `Ok("")` if the request was redirected (i.e. the user was created successfully
///
2023-10-04 12:06:58 +00:00
/// Returns `Ok(html)` if the request was not redirected (i.e. the user was not created successfully)
///
2023-10-04 12:06:58 +00:00
/// Returns `Err(err)` if there was an error
pub async fn create_user_request(url: String, body: String) -> Result<String, String> {
let classroom_url = std::env::var("CLASSROOM_URL").expect("CLASSROOM_URL env var is not set!");
ensure_session().await?;
// Get the stored client
let jar = SESSION_COOKIE.read().unwrap().jar.clone();
let uri = format!("{}{}", classroom_url, url);
// Do the request
let response = Request::post(uri)
.header("Content-Type", "multipart/form-data; boundary=---------------------------83919643214156711801978607619")
.cookie_jar(jar.clone())
.body(body)
.or_else(|err| Err(format!("Error creating request: {:?}", err)))?
.send();
let mut response = match response {
Ok(r) => r,
Err(err) => return Err(format!("Error sending request: {:?}", err)),
};
if response.status() == isahc::http::StatusCode::FOUND {
println!("Redirected!");
return Ok("".into());
2023-10-04 12:06:58 +00:00
}
match response.text() {
Ok(t) => Ok(t),
Err(err) => Err(format!("Error getting text from response: {:?}", err)),
}
}
/// Makes sure that the session cookie is set, and that it is valid
pub async fn ensure_session() -> Result<(), String> {
let last_usage_time = SESSION_TIME.read().unwrap().clone();
// Get current time in seconds
let current_time = SystemTime::now()
.duration_since(UNIX_EPOCH)
.expect("Time went backwards")
.as_secs();
let time_passed = current_time - last_usage_time;
// Default PHP session timeout is 1440 seconds. Use a 1400 seconds timeout to be safe
if time_passed > 1400 {
login().await?;
let mut time_ptr = SESSION_TIME.write().unwrap();
*time_ptr = current_time;
}
Ok(())
}
/// Logins to the online classroom, and sets the session cookie
async fn login() -> Result<(), String> {
2023-09-25 22:26:00 +00:00
let classroom_url = std::env::var("CLASSROOM_URL").expect("CLASSROOM_URL env var is not set!");
2023-09-30 16:16:20 +00:00
let classroom_user =
std::env::var("CLASSROOM_USER").expect("CLASSROOM_USER env var is not set!");
2023-09-30 16:16:20 +00:00
let classroom_password =
std::env::var("CLASSROOM_PASSWORD").expect("CLASSROOM_PASSWORD env var is not set!");
let jar = CookieJar::new();
let response = Request::post(format!("{}/index.php", classroom_url))
.header("Content-Type", "application/x-www-form-urlencoded")
.cookie_jar(jar.clone())
.body(format!(
"login={}&password={}&submitAuth=&_qf__formLogin=",
classroom_user, classroom_password
))
.unwrap()
.send();
match response {
Ok(_) => {
SESSION_COOKIE.write().unwrap().jar = jar.clone();
Ok(())
}
Err(error) => Err(format!("Error connecting to online classroom: {:?}", error)),
}
}