[BE] Create online classroom user

master
Araozu 2023-10-04 07:06:58 -05:00
parent adae0bd028
commit 9ba5a71928
5 changed files with 105 additions and 17 deletions

View File

@ -1,2 +1,5 @@
DATABASE_URL=mysql://user:password@localhost:3306/database DATABASE_URL=mysql://user:password@localhost:3306/database
RENIEC_API=B8RT6dKlN5DF408cD5vds RENIEC_API=B8RT6dKlN5DF408cD5vds
CLASSROOM_URL=https://testing.aulavirtual.eegsac.com
CLASSROOM_USER=user
CLASSROOM_PASSWORD=password

View File

@ -1,14 +1,14 @@
use rocket::{http::Status, serde::json::Json}; 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")] #[options("/classroom/user")]
pub fn create_user_options() -> Status { Status::Ok } pub fn create_user_options() -> Status { Status::Ok }
#[post("/classroom/user", format = "json", data = "<data>")] #[post("/classroom/user", format = "json", data = "<data>")]
pub fn create_user(data: Json<ClassroomPersonCreate>) -> (Status, Json<JsonResult<()>>) { pub async fn create_user(data: Json<ClassroomPersonCreate>) -> (Status, Json<JsonResult<()>>) {
match create(&data.0).await {
Ok(_) => return (Status::Ok, JsonResult::ok(())),
Err(err) => return (Status::InternalServerError, JsonResult::err(err)),
(Status::InternalServerError, JsonResult::err("Error creando usuario".into())) }
} }

View File

@ -1,9 +1,8 @@
use scraper::{Selector, Html}; 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; const CREATION_ERR: &str = "Creation successful, but linking failed";
use super::session::request;
/// Creates an online classroom user /// Creates an online classroom user
pub async fn create(data: &ClassroomPersonCreate) -> Result<(), String> { pub async fn create(data: &ClassroomPersonCreate) -> Result<(), String> {
@ -19,7 +18,44 @@ pub async fn create(data: &ClassroomPersonCreate) -> Result<(), String> {
&sec_token, &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<String, String> { async fn get_form_sec_token() -> Result<String, String> {

View File

@ -44,6 +44,49 @@ pub async fn request(url: String) -> Result<String, String> {
} }
} }
/// 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<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())
}
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 /// Makes sure that the session cookie is set, and that it is valid
pub async fn ensure_session() -> Result<(), String> { pub async fn ensure_session() -> Result<(), String> {
let last_usage_time = SESSION_TIME.read().unwrap().clone(); let last_usage_time = SESSION_TIME.read().unwrap().clone();

View File

@ -16,21 +16,27 @@ use urlencoding::encode;
#[get("/classroom/users/<full_name>")] #[get("/classroom/users/<full_name>")]
pub async fn get_users(full_name: String) -> (Status, Json<JsonResult<Vec<ClassroomPerson>>>) { pub async fn get_users(full_name: String) -> (Status, Json<JsonResult<Vec<ClassroomPerson>>>) {
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<Vec<ClassroomPerson>, String> {
let html = request(format!( let html = request(format!(
"/main/admin/user_list.php?keyword={}&submit=&_qf__search_simple=", "/main/admin/user_list.php?keyword={}&submit=&_qf__search_simple=",
encode(full_name.as_str()) encode(search_param.as_str())
)) )).await;
.await;
match html { match html {
Ok(html) => match parse_users(&html) { Ok(html) => match parse_users(&html) {
Ok(users) => (Status::Ok, JsonResult::ok(users)), Ok(users) => Ok(users),
Err(reason) => { Err(reason) => {
// println!("{}", html); // println!("{}", html);
(Status::InternalServerError, JsonResult::err(reason)) Err(reason)
} }
}, },
Err(reason) => (Status::InternalServerError, JsonResult::err(reason)), Err(reason) => Err(reason)
} }
} }