diff --git a/src/bin/update_data.rs b/src/bin/update_data.rs index 1c7d7ea..77e4d78 100644 --- a/src/bin/update_data.rs +++ b/src/bin/update_data.rs @@ -9,6 +9,7 @@ async fn main() -> tide::Result<()> { let db = db_init(&config).await.unwrap(); update_wolves(&config, &db).await; + update_wolves_id(&db).await; update_ldap(&config, &db).await; Ok(()) @@ -21,6 +22,30 @@ async fn update_wolves(config: &Config, db: &Pool) { } } +async fn update_wolves_id(db: &Pool) { + match sqlx::query( + "UPDATE accounts + SET id_wolves=( + SELECT id_wolves + FROM accounts_wolves + WHERE accounts.mail=accounts_wolves.email + ) + WHERE ( + SELECT id_wolves + FROM accounts_wolves + WHERE accounts.mail=accounts_wolves.email + ) IS NOT NULL", + ) + .execute(db) + .await + { + Ok(_) => {} + Err(e) => { + dbg!(e); + } + } +} + async fn update_ldap(config: &Config, db: &Pool) { let mut ldap = match LdapConn::new(&config.ldap_host) { Ok(s) => s, diff --git a/src/lib.rs b/src/lib.rs index 9711dbc..ba3aac2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -63,13 +63,13 @@ pub struct Accounts { pub async fn db_init(config: &Config) -> Result, Error> { let database = format!("{}/{}", &config.home, &config.database); let pool = SqlitePoolOptions::new() - .max_connections(5) - .connect_with( - SqliteConnectOptions::from_str(&format!("sqlite://{}", database))? - .foreign_keys(true) - .create_if_missing(true), - ) - .await?; + .max_connections(5) + .connect_with( + SqliteConnectOptions::from_str(&format!("sqlite://{}", database))? + .foreign_keys(true) + .create_if_missing(true), + ) + .await?; // migrations are amazing! sqlx::migrate!("./db").run(&pool).await?; diff --git a/src/methods/account_recover.rs b/src/methods/account_recover.rs index 12dab3b..f68b7b3 100644 --- a/src/methods/account_recover.rs +++ b/src/methods/account_recover.rs @@ -1,4 +1,4 @@ -use crate::{get_now_iso, random_string, uid_to_dn, Accounts, AccountsReset, Config, State}; +use crate::{get_now_iso, random_string, uid_to_dn, AccountsReset, Config, State}; use chrono::{Duration, SecondsFormat, Utc}; use ldap3::{exop::PasswordModify, LdapConn}; use lettre::{ @@ -15,6 +15,7 @@ use tide::{ pub mod password { use super::*; + use serde::Serialize; #[derive(Debug, Deserialize)] struct PassReset { @@ -49,19 +50,27 @@ pub mod password { Some(x) => x, }; - let mail_is_skynet = user_details.mail.trim().ends_with("@skynet.ie"); + let mut mails = vec![]; - // user does not have a different email address set - if mail_is_skynet && &user_details.student_id == "00000000" { - // not returning an error here as there is no need to let the person requesting what email the user has - return Ok(json!({"result": "success"}).into()); + // dummy mail to send to the studentmail. + if let Some(x) = check_email("dummy@skynet.ie", &user_details.student_id) { + if !mails.contains(&x) { + mails.push(x); + } + } + if let Some(x) = check_email(&user_details.mail, &user_details.student_id) { + if !mails.contains(&x) { + mails.push(x); + } + } + if let Some(x) = check_email(&user_details.email, &user_details.student_id) { + if !mails.contains(&x) { + mails.push(x); + } } - let mail = if mail_is_skynet { - format!("{}@studentmail.ul.ie", &user_details.student_id) - } else { - user_details.mail - }; + // auth is shared for all emails + let auth = random_string(50); // check if a recent password reset request happened lately db_pending_clear_expired(db).await?; @@ -71,21 +80,37 @@ pub mod password { return Ok(json!({"result": "success"}).into()); } - // send mail - let auth = random_string(50); - - match send_mail(config, &user_details.user, &mail, &auth) { - Ok(_) => { - save_to_db(db, &user_details.user, &auth).await?; - } - Err(e) => { - println!("{:?}", e); + for mail in mails { + // send mail + match send_mail(config, &user_details.user, &mail, &auth) { + Ok(_) => { + save_to_db(db, &user_details.user, &auth).await?; + } + Err(e) => { + println!("{:?}", e); + } } } Ok(json!({"result": "success"}).into()) } + fn check_email(mail: &str, student_id: &str) -> Option { + let mail_is_skynet = mail.trim().ends_with("@skynet.ie"); + + // user does not have a different email address set + if mail_is_skynet && student_id == "00000000" { + // not returning an error here as there is no need to let the person requesting what email the user has + return None; + } + + if mail_is_skynet { + Some(format!("{}@studentmail.ul.ie", student_id)) + } else { + Some(mail.to_string()) + } + } + #[derive(Debug, Deserialize)] pub struct PassResetAuth { auth: String, @@ -120,7 +145,14 @@ pub mod password { Ok(json!({"result": "success", "success": "Password set"}).into()) } - pub async fn db_get_user(pool: &Pool, user_in: &Option, mail_in: &Option) -> Option { + #[derive(Debug, Clone, Deserialize, Serialize, sqlx::FromRow)] + pub struct AccountsRecovery { + pub user: String, + pub mail: String, + pub student_id: String, + pub email: String, + } + pub async fn db_get_user(pool: &Pool, user_in: &Option, mail_in: &Option) -> Option { let user = match user_in { None => "", Some(x) => x, @@ -130,11 +162,11 @@ pub mod password { Some(x) => x, }; - if let Ok(res) = sqlx::query_as::<_, Accounts>( + if let Ok(res) = sqlx::query_as::<_, AccountsRecovery>( r#" SELECT * - FROM accounts - WHERE user == ? OR mail ==? + FROM accounts JOIN accounts_wolves ON accounts.id_wolves = accounts_wolves.id_wolves + WHERE accounts.user == ?1 OR accounts.mail == ?2 OR accounts_wolves.email == ?2 "#, ) .bind(user) @@ -316,7 +348,7 @@ pub mod password { } pub mod username { - use super::password::db_get_user; + use super::password::{db_get_user, AccountsRecovery}; use super::*; // far simpler, accept email, send notification via email @@ -360,7 +392,7 @@ pub mod username { Ok(json!({"result": "success"}).into()) } - fn send_mail(config: &Config, record: &Accounts) -> Result { + fn send_mail(config: &Config, record: &AccountsRecovery) -> Result { let recipient = &record.user; let mail = &record.mail; let discord = "https://discord.skynet.ie";