feat: final step in creating a new user

This commit is contained in:
silver 2023-06-04 19:39:01 +01:00
parent dcb4969b27
commit beab2cb97b
5 changed files with 135 additions and 14 deletions

23
Cargo.lock generated
View file

@ -78,6 +78,12 @@ dependencies = [
"version_check",
]
[[package]]
name = "android-tzdata"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0"
[[package]]
name = "android_system_properties"
version = "0.1.5"
@ -466,13 +472,13 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "chrono"
version = "0.4.24"
version = "0.4.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4e3c5919066adf22df73762e50cffcde3a758f2a848b113b586d1f86728b673b"
checksum = "ec837a71355b28f6556dbd569b37b3f363091c0bd4b2e735674521b4c5fd9bc5"
dependencies = [
"android-tzdata",
"iana-time-zone",
"js-sys",
"num-integer",
"num-traits",
"serde",
"time 0.1.45",
@ -1434,16 +1440,6 @@ dependencies = [
"minimal-lexical",
]
[[package]]
name = "num-integer"
version = "0.1.45"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9"
dependencies = [
"autocfg",
"num-traits",
]
[[package]]
name = "num-traits"
version = "0.2.15"
@ -1965,6 +1961,7 @@ name = "skynet_ldap_server"
version = "0.1.0"
dependencies = [
"async-std",
"chrono",
"dotenv",
"ldap3",
"rand 0.8.5",

View file

@ -25,3 +25,6 @@ surf = "2.3.2"
# create random strings
rand = "0.8.5"
# fancy time stuff
chrono = "0.4.26"

View file

@ -65,6 +65,8 @@ pub struct State {
#[derive(Debug, Clone)]
pub struct Config {
ldap_host: String,
ldap_admin: String,
ldap_admin_pw: String,
pub database: String,
pub host_port: String,
}
@ -75,6 +77,8 @@ pub fn get_config() -> Config {
// reasonable defaults
let mut config = Config {
ldap_host: "".to_string(),
ldap_admin: "".to_string(),
ldap_admin_pw: "".to_string(),
database: "database.db".to_string(),
host_port: "127.0.0.1:8087".to_string(),
};
@ -82,6 +86,12 @@ pub fn get_config() -> Config {
if let Ok(x) = env::var("LDAP_HOST") {
config.ldap_host = x.trim().to_string();
}
if let Ok(x) = env::var("LDAP_ADMIN") {
config.ldap_admin = x.trim().to_string();
}
if let Ok(x) = env::var("LDAP_ADMIN_PW") {
config.ldap_admin_pw = x.trim().to_string();
}
if let Ok(x) = env::var("DATABASE") {
config.database = x.trim().to_string();
}

View file

@ -1,6 +1,6 @@
use skynet_ldap_server::methods::account_update::post_update_ldap;
use skynet_ldap_server::{db_init, get_config, State};
use skynet_ldap_server::methods::account_new::post_new_account;
use skynet_ldap_server::methods::account_new::{post_new_account, post_new_account_confirmation};
#[async_std::main]
async fn main() -> tide::Result<()> {
@ -21,6 +21,7 @@ async fn main() -> tide::Result<()> {
app.at("/ldap/update").post(post_update_ldap);
app.at("/ldap/new").post(post_new_account);
app.at("/ldap/new/verify").post(post_new_account_confirmation);
app.listen(host_port).await?;
Ok(())

View file

@ -158,4 +158,114 @@ fn create_random_string(length: usize) -> String {
.take(length)
.map(char::from)
.collect()
}
#[derive(Debug, Deserialize)]
pub struct LdapNewUserVerify {
auth_code: String,
password: String
}
pub async fn post_new_account_confirmation(mut req: Request<State>) -> tide::Result {
let LdapNewUserVerify {
auth_code,
password
} = req.body_json().await?;
let State {
db,
config,
..
} = &req.state();
// make sure to clear out the expired ones first
db_pending_clear_expired(db).await;
// search db for auth_code
let results = sqlx::query_as::<_, AccountsPending>(
r#"
SELECT *
FROM accounts_pending
WHERE auth_code == ?
"#,
).bind(auth_code).fetch_all(db).await.unwrap_or(vec![]);
if results.is_empty() {
return Ok(json!({"result": "error"}).into());
}
let mut ldap = LdapConn::new(&config.ldap_host)?;
// need to bind as admin
ldap.simple_bind(&config.ldap_admin, &config.ldap_admin_pw)?.success()?;
let AccountsPending{ user, mail, name_first, name_second, auth_code, discord, expiry } = &results[0];
let dn = format!("uid={},ou=users,dc=skynet,dc=ie", user);
// TODO: find highrest uid number
let uid_number = "9990";
let home_directory = format!("/home/{}", user);
let password_tmp = create_random_string(50);
let cn = format!("{} {}", name_first, name_second);
let labeled_uri = format!("ldap:///ou=groups,dc=skynet,dc=ie??sub?(&(objectclass=posixgroup)(memberuid={}))", user);
let sk_mail = format!("{}@skynet.ie", user);
let sk_created = get_sk_created();
// create user
ldap.add(&dn, vec![
("objectClass", HashSet::from(["top", "person", "posixaccount", "ldapPublicKey", "inetOrgPerson", "skPerson"])),
// top
("ou", HashSet::from(["users"])),
// person
("uid", HashSet::from([user.as_str()])),
("cn", HashSet::from([cn.as_str()])),
// posixaccount
("uidNumber", HashSet::from([uid_number])),
("gidNumber", HashSet::from(["1001"])),
("homedirectory", HashSet::from([home_directory.as_str()])),
("userpassword", HashSet::from([password_tmp.as_str()])),
// inetOrgPerson
("mail", HashSet::from([mail.as_str()])),
("sn", HashSet::from([name_second.as_str()])),
// skPerson
("labeledURI", HashSet::from([labeled_uri.as_str()])),
("skMail", HashSet::from([sk_mail.as_str()])),
// need to get this from wolves
//("skID", HashSet::from(["12345678"])),
("skCreated", HashSet::from([sk_created.as_str()])),
])?.success()?;
// now to properly set teh password
let tmp = PasswordModify {
user_id: Some(&dn),
old_pass: Some(&password_tmp),
new_pass: Some(&password),
};
ldap.extended(tmp)?.success()?;
// done with ldap
ldap.unbind()?;
// delete from tmp db
if let Ok(results) = sqlx::query_as::<_, AccountsPending>(
r#"
DELETE FROM accounts_pending
WHERE auth_code == ?
"#,
).bind(&auth_code).fetch_all(pool).await {
println!("{:?}", results)
}
// frontend tells user that initial password ahs been sent to tehm
Ok(json!({"result": "success"}).into())
}
fn get_sk_created() -> String {
use chrono::{Utc};
let now = Utc::now();
format!("{}", now.format("%Y%m%d%H%M%SZ"))
}