Woo! Got db connections

This commit is contained in:
ViViDboarder 2019-02-13 16:02:33 -08:00
parent d3773a433a
commit 2de6ba6001
3 changed files with 123 additions and 0 deletions

View File

@ -99,6 +99,9 @@ handlebars = "1.1.0"
soup = "0.3.0" soup = "0.3.0"
regex = "1.1.0" regex = "1.1.0"
# LDAP libraries
ldap3 = "0.6"
[patch.crates-io] [patch.crates-io]
# Add support for Timestamp type # Add support for Timestamp type
rmp = { git = 'https://github.com/dani-garcia/msgpack-rust' } rmp = { git = 'https://github.com/dani-garcia/msgpack-rust' }

View File

@ -286,6 +286,28 @@ make_config! {
/// Password /// Password
smtp_password: Pass, true, option; smtp_password: Pass, true, option;
}, },
/// LDAP settings
ldap: _enable_ldap {
/// Enabled
_enable_ldap: bool, true, def, true;
/// Host
ldap_host: String, true, option;
/// Enable SSL
ldap_ssl: bool, true, def, false;
/// Port
ldap_port: u16, true, auto, |c| if c.ldap_ssl {636} else {389};
/// Bind dn
ldap_bind_dn: String, true, option;
/// Bind password
ldap_bind_password: Pass, true, option;
/// Search base dn
ldap_search_base_dn: String, true, option;
/// Search filter
ldap_search_filter: String, true, def, "(&(objectClass=*)(uid=*))".to_string();
/// Email field
ldap_mail_field: String, true, def, "mail".to_string();
},
} }
fn validate_config(cfg: &ConfigItems) -> Result<(), Error> { fn validate_config(cfg: &ConfigItems) -> Result<(), Error> {
@ -301,6 +323,10 @@ fn validate_config(cfg: &ConfigItems) -> Result<(), Error> {
err!("Both `SMTP_USERNAME` and `SMTP_PASSWORD` need to be set to enable email authentication") err!("Both `SMTP_USERNAME` and `SMTP_PASSWORD` need to be set to enable email authentication")
} }
if cfg.ldap_bind_dn.is_some() != cfg.ldap_bind_password.is_some() {
err!("Both `LDAP_BIND_DN` and `LDAP_BIND_PASSWORD` need to be set to enable ldap authentication")
}
Ok(()) Ok(())
} }
@ -398,6 +424,10 @@ impl Config {
let inner = &self.inner.read().unwrap().config; let inner = &self.inner.read().unwrap().config;
inner._enable_yubico && inner.yubico_client_id.is_some() && inner.yubico_secret_key.is_some() inner._enable_yubico && inner.yubico_client_id.is_some() && inner.yubico_secret_key.is_some()
} }
pub fn ldap_enabled(&self) -> bool {
let inner = &self.inner.read().unwrap().config;
inner._enable_ldap && inner.ldap_host.is_some() && inner.ldap_search_base_dn.is_some()
}
pub fn render_template<T: serde::ser::Serialize>( pub fn render_template<T: serde::ser::Serialize>(
&self, &self,

90
src/ldap.rs Normal file
View File

@ -0,0 +1,90 @@
extern crate ldap3;
use std::error::Error;
use ldap3::{DerefAliases, LdapConn, Scope, SearchEntry, SearchOptions};
use crate::db::models::User;
use crate::db::DbConn;
use crate::CONFIG;
fn main() {
match do_search() {
Ok(_) => (),
Err(e) => println!("{}", e),
}
}
/// Creates an LDAP connection, authenticating if necessary
fn ldap_client() -> Result<LdapConn, Box<Error>> {
let scheme = if CONFIG.ldap_ssl() { "ldaps" } else { "ldap" };
let host = CONFIG.ldap_host().unwrap();
let port = CONFIG.ldap_port().to_string();
let ldap = LdapConn::new(&format!("{}://{}:{}", scheme, host, port))?;
match (&CONFIG.ldap_bind_dn(), &CONFIG.ldap_bind_password()) {
(Some(bind_dn), Some(pass)) => {
match ldap.simple_bind(bind_dn, pass) {
_ => {}
};
}
(_, _) => {}
};
Ok(ldap)
}
/// Retrieves search results from ldap
fn search_entries() -> Result<Vec<SearchEntry>, Box<Error>> {
let ldap = ldap_client()?;
let mail_field = CONFIG.ldap_mail_field();
let fields = vec!["uid", "givenname", "sn", "cn", mail_field.as_str()];
// TODO: Something something error handling
let (results, _res) = ldap
.with_search_options(SearchOptions::new().deref(DerefAliases::Always))
.search(
&CONFIG.ldap_search_base_dn().unwrap(),
Scope::Subtree,
&CONFIG.ldap_search_filter(),
fields,
)?
.success()?;
// Build list of entries
let mut entries = Vec::new();
for result in results {
entries.push(SearchEntry::construct(result));
}
Ok(entries)
}
pub fn do_search() -> Result<(), Box<Error>> {
let mail_field = CONFIG.ldap_mail_field();
let entries = search_entries()?;
for user in entries {
println!("{:?}", user);
if let Some(user_email) = user.attrs[mail_field.as_str()].first() {
println!("{}", user_email);
}
}
Ok(())
}
pub fn invite_from_ldap(conn: DbConn) -> Result<(), Box<Error>> {
let mail_field = CONFIG.ldap_mail_field();
for ldap_user in search_entries()? {
if let Some(user_email) = ldap_user.attrs[mail_field.as_str()].first() {
let user = match User::find_by_mail(user_email.as_str(), &conn) {
Some(user) => println!("User already exists with email: {}", user_email),
None => println!("New user, should add to invites: {}", user_email),
};
}
}
Ok(())
}