feat: got started on allowing old members to set an email for password recovery

This commit is contained in:
silver 2023-08-16 00:02:44 +01:00
parent edb511b094
commit f41e0caa74
5 changed files with 588 additions and 13 deletions

View file

@ -422,3 +422,96 @@ pub mod username {
mailer.send(&email)
}
}
pub mod ssh {
use super::*;
use crate::AccountsSSH;
use ssh_key::AuthorizedKeys;
use std::fs;
// this is for a legacy member who has forgotten their account password to be able to set an email.
// With an email they can do a password recovery
#[derive(Debug, Deserialize)]
struct RequestChallenge {
user: String,
email: String,
}
#[derive(Debug, Deserialize)]
struct RequestResult {
auth: String,
keys: Vec<String>,
}
pub async fn request(mut req: Request<State>) -> tide::Result {
let RequestChallenge {
user,
email,
} = req.body_json().await?;
// check that any mail is not using @skynet.ie
if email.trim().ends_with("@skynet.ie") {
// all responses from this are a success
return Ok(json!({"result": "error", "error": "Skynet email not permitted."}).into());
}
// check if <root>/<user>/.ssh/authorized_keys exists
//let root = "/skynet_old";
let root = ".";
let path = format!("{}/{}/.ssh/authorized_keys", root, user);
let mut keys = vec![];
if fs::read_to_string(&path).is_ok() {
if let Ok(x) = AuthorizedKeys::read_file(path) {
for entry in x {
if let Ok(y) = entry.public_key().to_openssh() {
keys.push(y);
}
}
}
}
if keys.is_empty() {
return Ok(json!({ "result": "success", "success": { "auth": "", "keys": keys }}).into());
}
let db = &req.state().db;
// check if there is ane listing entry, use that auth if exists
if let Ok(result) = sqlx::query_as::<_, AccountsSSH>(
r#"
SELECT *
FROM accounts_ssh
WHERE user == ?
"#,
)
.bind(&user)
.fetch_one(db)
.await
{
return Ok(json!({ "result": "success", "success": { "auth": result.auth_code, "keys": keys }}).into());
}
// not in db, generate auth and save
let auth = random_string(50);
if sqlx::query_as::<_, AccountsSSH>(
"
INSERT OR REPLACE INTO accounts_ssh (user, auth_code, email)
VALUES (?1, ?2, ?3)
",
)
.bind(&user)
.bind(&auth)
.bind(&email)
.fetch_optional(db)
.await
.is_err()
{
// dont return any keys
return Ok(json!({ "result": "success", "success": { "auth": "", "keys": [] }}).into());
}
// return the full thing
Ok(json!({"result": "success","success": { "auth": auth,"keys": keys }}).into())
}
}