feat: final step in creating a new user
This commit is contained in:
parent
dcb4969b27
commit
beab2cb97b
5 changed files with 135 additions and 14 deletions
23
Cargo.lock
generated
23
Cargo.lock
generated
|
@ -78,6 +78,12 @@ dependencies = [
|
||||||
"version_check",
|
"version_check",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "android-tzdata"
|
||||||
|
version = "0.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "android_system_properties"
|
name = "android_system_properties"
|
||||||
version = "0.1.5"
|
version = "0.1.5"
|
||||||
|
@ -466,13 +472,13 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "chrono"
|
name = "chrono"
|
||||||
version = "0.4.24"
|
version = "0.4.26"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4e3c5919066adf22df73762e50cffcde3a758f2a848b113b586d1f86728b673b"
|
checksum = "ec837a71355b28f6556dbd569b37b3f363091c0bd4b2e735674521b4c5fd9bc5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"android-tzdata",
|
||||||
"iana-time-zone",
|
"iana-time-zone",
|
||||||
"js-sys",
|
"js-sys",
|
||||||
"num-integer",
|
|
||||||
"num-traits",
|
"num-traits",
|
||||||
"serde",
|
"serde",
|
||||||
"time 0.1.45",
|
"time 0.1.45",
|
||||||
|
@ -1434,16 +1440,6 @@ dependencies = [
|
||||||
"minimal-lexical",
|
"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]]
|
[[package]]
|
||||||
name = "num-traits"
|
name = "num-traits"
|
||||||
version = "0.2.15"
|
version = "0.2.15"
|
||||||
|
@ -1965,6 +1961,7 @@ name = "skynet_ldap_server"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async-std",
|
"async-std",
|
||||||
|
"chrono",
|
||||||
"dotenv",
|
"dotenv",
|
||||||
"ldap3",
|
"ldap3",
|
||||||
"rand 0.8.5",
|
"rand 0.8.5",
|
||||||
|
|
|
@ -25,3 +25,6 @@ surf = "2.3.2"
|
||||||
|
|
||||||
# create random strings
|
# create random strings
|
||||||
rand = "0.8.5"
|
rand = "0.8.5"
|
||||||
|
|
||||||
|
# fancy time stuff
|
||||||
|
chrono = "0.4.26"
|
||||||
|
|
10
src/lib.rs
10
src/lib.rs
|
@ -65,6 +65,8 @@ pub struct State {
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct Config {
|
pub struct Config {
|
||||||
ldap_host: String,
|
ldap_host: String,
|
||||||
|
ldap_admin: String,
|
||||||
|
ldap_admin_pw: String,
|
||||||
pub database: String,
|
pub database: String,
|
||||||
pub host_port: String,
|
pub host_port: String,
|
||||||
}
|
}
|
||||||
|
@ -75,6 +77,8 @@ pub fn get_config() -> Config {
|
||||||
// reasonable defaults
|
// reasonable defaults
|
||||||
let mut config = Config {
|
let mut config = Config {
|
||||||
ldap_host: "".to_string(),
|
ldap_host: "".to_string(),
|
||||||
|
ldap_admin: "".to_string(),
|
||||||
|
ldap_admin_pw: "".to_string(),
|
||||||
database: "database.db".to_string(),
|
database: "database.db".to_string(),
|
||||||
host_port: "127.0.0.1:8087".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") {
|
if let Ok(x) = env::var("LDAP_HOST") {
|
||||||
config.ldap_host = x.trim().to_string();
|
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") {
|
if let Ok(x) = env::var("DATABASE") {
|
||||||
config.database = x.trim().to_string();
|
config.database = x.trim().to_string();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use skynet_ldap_server::methods::account_update::post_update_ldap;
|
use skynet_ldap_server::methods::account_update::post_update_ldap;
|
||||||
use skynet_ldap_server::{db_init, get_config, State};
|
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_std::main]
|
||||||
async fn main() -> tide::Result<()> {
|
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/update").post(post_update_ldap);
|
||||||
|
|
||||||
app.at("/ldap/new").post(post_new_account);
|
app.at("/ldap/new").post(post_new_account);
|
||||||
|
app.at("/ldap/new/verify").post(post_new_account_confirmation);
|
||||||
|
|
||||||
app.listen(host_port).await?;
|
app.listen(host_port).await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -159,3 +159,113 @@ fn create_random_string(length: usize) -> String {
|
||||||
.map(char::from)
|
.map(char::from)
|
||||||
.collect()
|
.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"))
|
||||||
|
}
|
Loading…
Reference in a new issue