feat: split up into seperate modules before it gets too tangled up
This commit is contained in:
parent
82ce0a864f
commit
9b52052add
4 changed files with 117 additions and 117 deletions
40
src/lib.rs
40
src/lib.rs
|
@ -1,6 +1,8 @@
|
||||||
|
pub mod methods;
|
||||||
|
use dotenv::dotenv;
|
||||||
use sqlx::sqlite::{SqliteConnectOptions, SqlitePoolOptions};
|
use sqlx::sqlite::{SqliteConnectOptions, SqlitePoolOptions};
|
||||||
use sqlx::{Error, Pool, Sqlite};
|
use sqlx::{Error, Pool, Sqlite};
|
||||||
|
use std::env;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use std::time::{SystemTime, UNIX_EPOCH};
|
use std::time::{SystemTime, UNIX_EPOCH};
|
||||||
|
|
||||||
|
@ -41,3 +43,39 @@ pub fn get_now() -> i64 {
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct State {
|
||||||
|
pub db: Pool<Sqlite>,
|
||||||
|
pub config: Config,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct Config {
|
||||||
|
ldap_host: String,
|
||||||
|
pub database: String,
|
||||||
|
pub host_port: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_config() -> Config {
|
||||||
|
dotenv().ok();
|
||||||
|
|
||||||
|
// reasonable defaults
|
||||||
|
let mut config = Config {
|
||||||
|
ldap_host: "".to_string(),
|
||||||
|
database: "database.db".to_string(),
|
||||||
|
host_port: "127.0.0.1:8087".to_string(),
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Ok(x) = env::var("LDAP_HOST") {
|
||||||
|
config.ldap_host = x.trim().to_string();
|
||||||
|
}
|
||||||
|
if let Ok(x) = env::var("DATABASE") {
|
||||||
|
config.database = x.trim().to_string();
|
||||||
|
}
|
||||||
|
if let Ok(x) = env::var("HOST_PORT") {
|
||||||
|
config.host_port = x.trim().to_string();
|
||||||
|
}
|
||||||
|
|
||||||
|
config
|
||||||
|
}
|
||||||
|
|
118
src/main.rs
118
src/main.rs
|
@ -1,21 +1,5 @@
|
||||||
use ldap3::{LdapConn, Mod, Scope, SearchEntry};
|
use skynet_ldap_server::methods::change_details::post_update_ldap;
|
||||||
|
use skynet_ldap_server::{db_init, get_config, State};
|
||||||
use ldap3::exop::PasswordModify;
|
|
||||||
use std::collections::HashSet;
|
|
||||||
|
|
||||||
// for teh webserver
|
|
||||||
use dotenv::dotenv;
|
|
||||||
use skynet_ldap_server::db_init;
|
|
||||||
use sqlx::{Pool, Sqlite};
|
|
||||||
use std::env;
|
|
||||||
use tide::prelude::{json, Deserialize};
|
|
||||||
use tide::Request;
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
struct State {
|
|
||||||
db: Pool<Sqlite>,
|
|
||||||
config: Config,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[async_std::main]
|
#[async_std::main]
|
||||||
async fn main() -> tide::Result<()> {
|
async fn main() -> tide::Result<()> {
|
||||||
|
@ -39,104 +23,6 @@ async fn main() -> tide::Result<()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
struct Config {
|
|
||||||
ldap_host: String,
|
|
||||||
database: String,
|
|
||||||
host_port: String,
|
|
||||||
}
|
|
||||||
fn get_config() -> Config {
|
|
||||||
dotenv().ok();
|
|
||||||
|
|
||||||
// reasonable defaults
|
|
||||||
let mut config = Config {
|
|
||||||
ldap_host: "".to_string(),
|
|
||||||
database: "database.db".to_string(),
|
|
||||||
host_port: "127.0.0.1:8087".to_string(),
|
|
||||||
};
|
|
||||||
|
|
||||||
if let Ok(x) = env::var("LDAP_HOST") {
|
|
||||||
config.ldap_host = x.trim().to_string();
|
|
||||||
}
|
|
||||||
if let Ok(x) = env::var("DATABASE") {
|
|
||||||
config.database = x.trim().to_string();
|
|
||||||
}
|
|
||||||
if let Ok(x) = env::var("HOST_PORT") {
|
|
||||||
config.host_port = x.trim().to_string();
|
|
||||||
}
|
|
||||||
|
|
||||||
config
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Deserialize)]
|
|
||||||
struct LdapUpdate {
|
|
||||||
user: String,
|
|
||||||
pass: String,
|
|
||||||
field: String,
|
|
||||||
value: String,
|
|
||||||
}
|
|
||||||
async fn post_update_ldap(mut req: Request<State>) -> tide::Result {
|
|
||||||
let LdapUpdate {
|
|
||||||
user,
|
|
||||||
pass,
|
|
||||||
field,
|
|
||||||
value,
|
|
||||||
} = req.body_json().await?;
|
|
||||||
|
|
||||||
let config = &req.state().config;
|
|
||||||
|
|
||||||
// easier to give each request its own connection
|
|
||||||
let mut ldap = LdapConn::new(&config.ldap_host)?;
|
|
||||||
|
|
||||||
let dn = format!("uid={},ou=users,dc=skynet,dc=ie", user);
|
|
||||||
ldap.simple_bind(&dn, &pass)?.success()?;
|
|
||||||
|
|
||||||
// always assume insecure
|
|
||||||
let mut pw_keep_same = false;
|
|
||||||
|
|
||||||
// get the users current password hash
|
|
||||||
let (rs, _res) = ldap.search(&dn, Scope::Base, "(objectClass=*)", vec!["userPassword"])?.success()?;
|
|
||||||
if !rs.is_empty() {
|
|
||||||
let tmp = SearchEntry::construct(rs[0].clone());
|
|
||||||
if !tmp.attrs["userPassword"].is_empty() && tmp.attrs["userPassword"][0].starts_with("{SSHA512}") {
|
|
||||||
pw_keep_same = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// check if the password field itself is being updated
|
|
||||||
let (pass_old, pass_new) = if &field != "userPassword" {
|
|
||||||
// if password is not being updated then just update the required field
|
|
||||||
let mods = vec![Mod::Replace(field, HashSet::from([value]))];
|
|
||||||
ldap.modify(&dn, mods)?.success()?;
|
|
||||||
|
|
||||||
// pass back the "old" and "new" passwords
|
|
||||||
(pass.clone(), pass.clone())
|
|
||||||
} else {
|
|
||||||
// password is going to be updated, even if the old value is not starting with "{SSHA512}"
|
|
||||||
|
|
||||||
pw_keep_same = false;
|
|
||||||
(pass.clone(), value)
|
|
||||||
};
|
|
||||||
|
|
||||||
if !pw_keep_same {
|
|
||||||
// really easy to update password once ye know how
|
|
||||||
|
|
||||||
let tmp = PasswordModify {
|
|
||||||
// none as we are staying on the same connection
|
|
||||||
user_id: None,
|
|
||||||
|
|
||||||
old_pass: Some(&pass_old),
|
|
||||||
new_pass: Some(&pass_new),
|
|
||||||
};
|
|
||||||
|
|
||||||
ldap.extended(tmp)?.success()?;
|
|
||||||
};
|
|
||||||
|
|
||||||
ldap.unbind()?;
|
|
||||||
|
|
||||||
Ok(json!({"result": "success"}).into())
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Create new account
|
/* Create new account
|
||||||
|
|
||||||
|
|
||||||
|
|
75
src/methods/change_details.rs
Normal file
75
src/methods/change_details.rs
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
use crate::State;
|
||||||
|
use ldap3::exop::PasswordModify;
|
||||||
|
use ldap3::{LdapConn, Mod, Scope, SearchEntry};
|
||||||
|
use std::collections::HashSet;
|
||||||
|
use tide::prelude::{json, Deserialize};
|
||||||
|
use tide::Request;
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
pub struct LdapUpdate {
|
||||||
|
user: String,
|
||||||
|
pass: String,
|
||||||
|
field: String,
|
||||||
|
value: String,
|
||||||
|
}
|
||||||
|
pub async fn post_update_ldap(mut req: Request<State>) -> tide::Result {
|
||||||
|
let LdapUpdate {
|
||||||
|
user,
|
||||||
|
pass,
|
||||||
|
field,
|
||||||
|
value,
|
||||||
|
} = req.body_json().await?;
|
||||||
|
|
||||||
|
let config = &req.state().config;
|
||||||
|
|
||||||
|
// easier to give each request its own connection
|
||||||
|
let mut ldap = LdapConn::new(&config.ldap_host)?;
|
||||||
|
|
||||||
|
let dn = format!("uid={},ou=users,dc=skynet,dc=ie", user);
|
||||||
|
ldap.simple_bind(&dn, &pass)?.success()?;
|
||||||
|
|
||||||
|
// always assume insecure
|
||||||
|
let mut pw_keep_same = false;
|
||||||
|
|
||||||
|
// get the users current password hash
|
||||||
|
let (rs, _res) = ldap.search(&dn, Scope::Base, "(objectClass=*)", vec!["userPassword"])?.success()?;
|
||||||
|
if !rs.is_empty() {
|
||||||
|
let tmp = SearchEntry::construct(rs[0].clone());
|
||||||
|
if !tmp.attrs["userPassword"].is_empty() && tmp.attrs["userPassword"][0].starts_with("{SSHA512}") {
|
||||||
|
pw_keep_same = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if the password field itself is being updated
|
||||||
|
let (pass_old, pass_new) = if &field != "userPassword" {
|
||||||
|
// if password is not being updated then just update the required field
|
||||||
|
let mods = vec![Mod::Replace(field, HashSet::from([value]))];
|
||||||
|
ldap.modify(&dn, mods)?.success()?;
|
||||||
|
|
||||||
|
// pass back the "old" and "new" passwords
|
||||||
|
(pass.clone(), pass.clone())
|
||||||
|
} else {
|
||||||
|
// password is going to be updated, even if the old value is not starting with "{SSHA512}"
|
||||||
|
|
||||||
|
pw_keep_same = false;
|
||||||
|
(pass.clone(), value)
|
||||||
|
};
|
||||||
|
|
||||||
|
if !pw_keep_same {
|
||||||
|
// really easy to update password once ye know how
|
||||||
|
|
||||||
|
let tmp = PasswordModify {
|
||||||
|
// none as we are staying on the same connection
|
||||||
|
user_id: None,
|
||||||
|
|
||||||
|
old_pass: Some(&pass_old),
|
||||||
|
new_pass: Some(&pass_new),
|
||||||
|
};
|
||||||
|
|
||||||
|
ldap.extended(tmp)?.success()?;
|
||||||
|
};
|
||||||
|
|
||||||
|
ldap.unbind()?;
|
||||||
|
|
||||||
|
Ok(json!({"result": "success"}).into())
|
||||||
|
}
|
1
src/methods/mod.rs
Normal file
1
src/methods/mod.rs
Normal file
|
@ -0,0 +1 @@
|
||||||
|
pub mod change_details;
|
Loading…
Reference in a new issue