eeg_certs/backend/src/online_classroom/create_user.rs

269 lines
8.3 KiB
Rust

use super::session::{create_user_request, request};
use crate::model::{classroom_user::ClassroomPersonCreate, person::PersonLink};
use scraper::{Html, Selector};
const CREATION_ERR: &str = "Creation successful, but linking failed";
/// Creates an online classroom user
pub async fn create(data: &ClassroomPersonCreate) -> Result<PersonLink, String> {
let sec_token = get_form_sec_token().await?;
let body = get_request_body(
&data.person_surnames,
&data.person_names,
&data.person_email,
&data.person_username,
&data.person_password,
&data.person_expiration_date,
&sec_token,
);
// 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 person_link = PersonLink {
person_id: data.person_id,
person_classroom_id: user_id,
person_classroom_username: data.person_username.clone(),
};
let result = person_link.insert().await;
match result {
Ok(_) => return Ok(person_link),
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> {
let creation_form = request("/main/admin/user_add.php".into()).await?;
let sec_token_selector = Selector::parse("#user_add_sec_token")
.or_else(|err| Err(format!("Error creating sec_token selector: {:?}", err)))?;
let fragment = Html::parse_document(&creation_form);
let input_element = match fragment.select(&sec_token_selector).next() {
Some(el) => el,
None => return Err(format!("Error selecting sec_token element. Not found")),
};
let sec_token_value = match input_element.value().attr("value") {
Some(val) => val,
None => {
return Err(format!(
"Error getting sec_token value from input. Not found"
))
}
};
Ok(sec_token_value.into())
}
fn get_request_body(
surnames: &String,
names: &String,
email: &String,
username: &String,
password: &String,
expiration_date: &String,
sec_token: &String,
) -> String {
format!(
r#"
-----------------------------83919643214156711801978607619
Content-Disposition: form-data; name="lastname"
{surnames}
-----------------------------83919643214156711801978607619
Content-Disposition: form-data; name="firstname"
{names}
-----------------------------83919643214156711801978607619
Content-Disposition: form-data; name="official_code"
{password}
-----------------------------83919643214156711801978607619
Content-Disposition: form-data; name="email"
{email}
-----------------------------83919643214156711801978607619
Content-Disposition: form-data; name="phone"
-----------------------------83919643214156711801978607619
Content-Disposition: form-data; name="picture"; filename=""
Content-Type: application/octet-stream
-----------------------------83919643214156711801978607619
Content-Disposition: form-data; name="username"
{username}
-----------------------------83919643214156711801978607619
Content-Disposition: form-data; name="password[password_auto]"
0
-----------------------------83919643214156711801978607619
Content-Disposition: form-data; name="password[password]"
{password}
-----------------------------83919643214156711801978607619
Content-Disposition: form-data; name="status"
5
-----------------------------83919643214156711801978607619
Content-Disposition: form-data; name="admin[platform_admin]"
0
-----------------------------83919643214156711801978607619
Content-Disposition: form-data; name="language"
spanish
-----------------------------83919643214156711801978607619
Content-Disposition: form-data; name="mail[send_mail]"
1
-----------------------------83919643214156711801978607619
Content-Disposition: form-data; name="radio_expiration_date"
1
-----------------------------83919643214156711801978607619
Content-Disposition: form-data; name="expiration_date"
{expiration_date} 23:59
-----------------------------83919643214156711801978607619
Content-Disposition: form-data; name="active"
1
-----------------------------83919643214156711801978607619
Content-Disposition: form-data; name="extra_legal_accept"
-----------------------------83919643214156711801978607619
Content-Disposition: form-data; name="extra_already_logged_in"
-----------------------------83919643214156711801978607619
Content-Disposition: form-data; name="extra_update_type"
-----------------------------83919643214156711801978607619
Content-Disposition: form-data; name="extra_rssfeeds"
-----------------------------83919643214156711801978607619
Content-Disposition: form-data; name="extra_dashboard"
-----------------------------83919643214156711801978607619
Content-Disposition: form-data; name="extra_timezone"
-----------------------------83919643214156711801978607619
Content-Disposition: form-data; name="extra_mail_notify_invitation"
1
-----------------------------83919643214156711801978607619
Content-Disposition: form-data; name="extra_mail_notify_message"
1
-----------------------------83919643214156711801978607619
Content-Disposition: form-data; name="extra_mail_notify_group_message"
1
-----------------------------83919643214156711801978607619
Content-Disposition: form-data; name="extra_user_chat_status"
-----------------------------83919643214156711801978607619
Content-Disposition: form-data; name="extra_google_calendar_url"
-----------------------------83919643214156711801978607619
Content-Disposition: form-data; name="extra_captcha_blocked_until_date"
-----------------------------83919643214156711801978607619
Content-Disposition: form-data; name="extra_skype"
-----------------------------83919643214156711801978607619
Content-Disposition: form-data; name="extra_linkedin_url"
-----------------------------83919643214156711801978607619
Content-Disposition: form-data; name="extra_request_for_legal_agreement_consent_removal_justification"
-----------------------------83919643214156711801978607619
Content-Disposition: form-data; name="extra_request_for_delete_account_justification"
-----------------------------83919643214156711801978607619
Content-Disposition: form-data; name="extra_request_for_legal_agreement_consent_removal"
-----------------------------83919643214156711801978607619
Content-Disposition: form-data; name="extra_request_for_delete_account"
-----------------------------83919643214156711801978607619
Content-Disposition: form-data; name="submit"
-----------------------------83919643214156711801978607619
Content-Disposition: form-data; name="_qf__user_add"
-----------------------------83919643214156711801978607619
Content-Disposition: form-data; name="MAX_FILE_SIZE"
536870912
-----------------------------83919643214156711801978607619
Content-Disposition: form-data; name="picture_crop_result"
-----------------------------83919643214156711801978607619
Content-Disposition: form-data; name="picture_crop_image_base_64"
-----------------------------83919643214156711801978607619
Content-Disposition: form-data; name="item_id"
0
-----------------------------83919643214156711801978607619
Content-Disposition: form-data; name="sec_token"
{sec_token}
-----------------------------83919643214156711801978607619--
"#
)
}