diff --git a/backend/.env.example b/backend/.env.example index 61445d0..d25237e 100644 --- a/backend/.env.example +++ b/backend/.env.example @@ -1,2 +1,5 @@ DATABASE_URL=mysql://user:password@localhost:3306/database RENIEC_API=B8RT6dKlN5DF408cD5vds +CLASSROOM_URL=https://testing.aulavirtual.eegsac.com +CLASSROOM_USER=user +CLASSROOM_PASSWORD=password diff --git a/backend/src/controller/classroom/mod.rs b/backend/src/controller/classroom/mod.rs index 9496946..aa69020 100644 --- a/backend/src/controller/classroom/mod.rs +++ b/backend/src/controller/classroom/mod.rs @@ -1,14 +1,14 @@ use rocket::{http::Status, serde::json::Json}; -use crate::{json_result::JsonResult, model::classroom_user::ClassroomPersonCreate}; +use crate::{json_result::JsonResult, model::classroom_user::ClassroomPersonCreate, online_classroom::create_user::create}; #[options("/classroom/user")] pub fn create_user_options() -> Status { Status::Ok } #[post("/classroom/user", format = "json", data = "")] -pub fn create_user(data: Json) -> (Status, Json>) { - - - - (Status::InternalServerError, JsonResult::err("Error creando usuario".into())) +pub async fn create_user(data: Json) -> (Status, Json>) { + match create(&data.0).await { + Ok(_) => return (Status::Ok, JsonResult::ok(())), + Err(err) => return (Status::InternalServerError, JsonResult::err(err)), + } } diff --git a/backend/src/online_classroom/create_user.rs b/backend/src/online_classroom/create_user.rs index 5c5805b..2cc9e86 100644 --- a/backend/src/online_classroom/create_user.rs +++ b/backend/src/online_classroom/create_user.rs @@ -1,9 +1,8 @@ use scraper::{Selector, Html}; +use crate::model::{classroom_user::ClassroomPersonCreate, person::PersonLink}; +use super::session::{request, create_user_request}; -use crate::model::classroom_user::ClassroomPersonCreate; - -use super::session::request; - +const CREATION_ERR: &str = "Creation successful, but linking failed"; /// Creates an online classroom user pub async fn create(data: &ClassroomPersonCreate) -> Result<(), String> { @@ -19,7 +18,44 @@ pub async fn create(data: &ClassroomPersonCreate) -> Result<(), String> { &sec_token, ); - Err("Not implemented".into()) + // Do create + let response = create_user_request("/main/admin/user_add.php".into(), body).await?; + + if response.is_empty() { + // User created successfully. + // Have to find its user_id, and link it to the person + let users = super::user::get_users_impl(data.person_username.clone()).await; + + match users { + Ok(user) if user.len() == 1 => { + let user_id: i32 = user[0].user_id.parse() + .or_else(|err| Err(format!("{}: Error parsing user_id: {:?}", CREATION_ERR, err)))?; + + let result = PersonLink { + person_id: data.person_id, + person_classroom_id: user_id, + }.insert().await; + + match result { + Ok(_) => return Ok(()), + Err(reason) => { + return Err(format!("{}: {}", CREATION_ERR, reason)) + } + } + } + Ok(u) if u.is_empty() => { + return Err(format!("{}: No users with username {} found", CREATION_ERR, data.person_username)) + } + Ok(_) => { + return Err(format!("{}: More than 1 user found", CREATION_ERR)) + } + Err(reason) => { + return Err(format!("{}: {}", CREATION_ERR, reason)) + } + } + } + + Err("Expected empty body, found something else".into()) } async fn get_form_sec_token() -> Result { diff --git a/backend/src/online_classroom/session.rs b/backend/src/online_classroom/session.rs index efb6ff0..7ccce81 100644 --- a/backend/src/online_classroom/session.rs +++ b/backend/src/online_classroom/session.rs @@ -44,6 +44,49 @@ pub async fn request(url: String) -> Result { } } + +/// Handles request for creating a user. +/// +/// Returns `Ok("")` if the request was redirected (i.e. the user was created successfully +/// +/// Returns `Ok(html)` if the request was not redirected (i.e. the user was not created successfully) +/// +/// Returns `Err(err)` if there was an error +pub async fn create_user_request(url: String, body: String) -> Result { + 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()) + } + + 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(); diff --git a/backend/src/online_classroom/user.rs b/backend/src/online_classroom/user.rs index 5f0fe05..8dc916d 100644 --- a/backend/src/online_classroom/user.rs +++ b/backend/src/online_classroom/user.rs @@ -16,21 +16,27 @@ use urlencoding::encode; #[get("/classroom/users/")] pub async fn get_users(full_name: String) -> (Status, Json>>) { + match get_users_impl(full_name).await { + Ok(users) => (Status::Ok, JsonResult::ok(users)), + Err(reason) => (Status::InternalServerError, JsonResult::err(reason)), + } +} + +pub async fn get_users_impl(search_param: String) -> Result, String> { let html = request(format!( "/main/admin/user_list.php?keyword={}&submit=&_qf__search_simple=", - encode(full_name.as_str()) - )) - .await; + encode(search_param.as_str()) + )).await; match html { Ok(html) => match parse_users(&html) { - Ok(users) => (Status::Ok, JsonResult::ok(users)), + Ok(users) => Ok(users), Err(reason) => { // println!("{}", html); - (Status::InternalServerError, JsonResult::err(reason)) + Err(reason) } }, - Err(reason) => (Status::InternalServerError, JsonResult::err(reason)), + Err(reason) => Err(reason) } }