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();
|
let db = db_init(&config).await.unwrap();
|
||||||
|
|
||||||
update_wolves(&config, &db).await;
|
update_wolves(&config, &db).await;
|
||||||
|
update_wolves_id(&db).await;
|
||||||
update_ldap(&config, &db).await;
|
update_ldap(&config, &db).await;
|
||||||
|
|
||||||
Ok(())
|
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>) {
|
async fn update_ldap(config: &Config, db: &Pool<Sqlite>) {
|
||||||
let mut ldap = match LdapConn::new(&config.ldap_host) {
|
let mut ldap = match LdapConn::new(&config.ldap_host) {
|
||||||
Ok(s) => s,
|
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> {
|
pub async fn db_init(config: &Config) -> Result<Pool<Sqlite>, Error> {
|
||||||
let database = format!("{}/{}", &config.home, &config.database);
|
let database = format!("{}/{}", &config.home, &config.database);
|
||||||
let pool = SqlitePoolOptions::new()
|
let pool = SqlitePoolOptions::new()
|
||||||
.max_connections(5)
|
.max_connections(5)
|
||||||
.connect_with(
|
.connect_with(
|
||||||
SqliteConnectOptions::from_str(&format!("sqlite://{}", database))?
|
SqliteConnectOptions::from_str(&format!("sqlite://{}", database))?
|
||||||
.foreign_keys(true)
|
.foreign_keys(true)
|
||||||
.create_if_missing(true),
|
.create_if_missing(true),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
// migrations are amazing!
|
// migrations are amazing!
|
||||||
sqlx::migrate!("./db").run(&pool).await?;
|
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 chrono::{Duration, SecondsFormat, Utc};
|
||||||
use ldap3::{exop::PasswordModify, LdapConn};
|
use ldap3::{exop::PasswordModify, LdapConn};
|
||||||
use lettre::{
|
use lettre::{
|
||||||
|
@ -15,6 +15,7 @@ use tide::{
|
||||||
|
|
||||||
pub mod password {
|
pub mod password {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use serde::Serialize;
|
||||||
|
|
||||||
#[derive(Debug, Deserialize)]
|
#[derive(Debug, Deserialize)]
|
||||||
struct PassReset {
|
struct PassReset {
|
||||||
|
@ -49,19 +50,27 @@ pub mod password {
|
||||||
Some(x) => x,
|
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
|
// dummy mail to send to the studentmail.
|
||||||
if mail_is_skynet && &user_details.student_id == "00000000" {
|
if let Some(x) = check_email("dummy@skynet.ie", &user_details.student_id) {
|
||||||
// not returning an error here as there is no need to let the person requesting what email the user has
|
if !mails.contains(&x) {
|
||||||
return Ok(json!({"result": "success"}).into());
|
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 {
|
// auth is shared for all emails
|
||||||
format!("{}@studentmail.ul.ie", &user_details.student_id)
|
let auth = random_string(50);
|
||||||
} else {
|
|
||||||
user_details.mail
|
|
||||||
};
|
|
||||||
|
|
||||||
// check if a recent password reset request happened lately
|
// check if a recent password reset request happened lately
|
||||||
db_pending_clear_expired(db).await?;
|
db_pending_clear_expired(db).await?;
|
||||||
|
@ -71,21 +80,37 @@ pub mod password {
|
||||||
return Ok(json!({"result": "success"}).into());
|
return Ok(json!({"result": "success"}).into());
|
||||||
}
|
}
|
||||||
|
|
||||||
// send mail
|
for mail in mails {
|
||||||
let auth = random_string(50);
|
// send mail
|
||||||
|
match send_mail(config, &user_details.user, &mail, &auth) {
|
||||||
match send_mail(config, &user_details.user, &mail, &auth) {
|
Ok(_) => {
|
||||||
Ok(_) => {
|
save_to_db(db, &user_details.user, &auth).await?;
|
||||||
save_to_db(db, &user_details.user, &auth).await?;
|
}
|
||||||
}
|
Err(e) => {
|
||||||
Err(e) => {
|
println!("{:?}", e);
|
||||||
println!("{:?}", e);
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(json!({"result": "success"}).into())
|
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)]
|
#[derive(Debug, Deserialize)]
|
||||||
pub struct PassResetAuth {
|
pub struct PassResetAuth {
|
||||||
auth: String,
|
auth: String,
|
||||||
|
@ -120,7 +145,14 @@ pub mod password {
|
||||||
Ok(json!({"result": "success", "success": "Password set"}).into())
|
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 {
|
let user = match user_in {
|
||||||
None => "",
|
None => "",
|
||||||
Some(x) => x,
|
Some(x) => x,
|
||||||
|
@ -130,11 +162,11 @@ pub mod password {
|
||||||
Some(x) => x,
|
Some(x) => x,
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Ok(res) = sqlx::query_as::<_, Accounts>(
|
if let Ok(res) = sqlx::query_as::<_, AccountsRecovery>(
|
||||||
r#"
|
r#"
|
||||||
SELECT *
|
SELECT *
|
||||||
FROM accounts
|
FROM accounts JOIN accounts_wolves ON accounts.id_wolves = accounts_wolves.id_wolves
|
||||||
WHERE user == ? OR mail ==?
|
WHERE accounts.user == ?1 OR accounts.mail == ?2 OR accounts_wolves.email == ?2
|
||||||
"#,
|
"#,
|
||||||
)
|
)
|
||||||
.bind(user)
|
.bind(user)
|
||||||
|
@ -316,7 +348,7 @@ pub mod password {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub mod username {
|
pub mod username {
|
||||||
use super::password::db_get_user;
|
use super::password::{db_get_user, AccountsRecovery};
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
// far simpler, accept email, send notification via email
|
// far simpler, accept email, send notification via email
|
||||||
|
@ -360,7 +392,7 @@ pub mod username {
|
||||||
Ok(json!({"result": "success"}).into())
|
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 recipient = &record.user;
|
||||||
let mail = &record.mail;
|
let mail = &record.mail;
|
||||||
let discord = "https://discord.skynet.ie";
|
let discord = "https://discord.skynet.ie";
|
||||||
|
|
Loading…
Add table
Reference in a new issue