feat: now sends a reset pw mail to all connected emails
This commit is contained in:
parent
6510696851
commit
b00b5cac6d
3 changed files with 90 additions and 33 deletions
|
@ -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<Sqlite>) {
|
|||
}
|
||||
}
|
||||
|
||||
async fn update_wolves_id(db: &Pool<Sqlite>) {
|
||||
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<Sqlite>) {
|
||||
let mut ldap = match LdapConn::new(&config.ldap_host) {
|
||||
Ok(s) => s,
|
||||
|
|
14
src/lib.rs
14
src/lib.rs
|
@ -63,13 +63,13 @@ pub struct Accounts {
|
|||
pub async fn db_init(config: &Config) -> Result<Pool<Sqlite>, 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?;
|
||||
|
|
|
@ -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<String> {
|
||||
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<Sqlite>, user_in: &Option<String>, mail_in: &Option<String>) -> Option<Accounts> {
|
||||
#[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<Sqlite>, user_in: &Option<String>, mail_in: &Option<String>) -> Option<AccountsRecovery> {
|
||||
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<Response, Error> {
|
||||
fn send_mail(config: &Config, record: &AccountsRecovery) -> Result<Response, Error> {
|
||||
let recipient = &record.user;
|
||||
let mail = &record.mail;
|
||||
let discord = "https://discord.skynet.ie";
|
||||
|
|
Loading…
Add table
Reference in a new issue