|
|
@ -5,9 +5,9 @@ extern crate tokio_timer; |
|
|
|
|
|
|
|
use std::error::Error; |
|
|
|
use std::thread; |
|
|
|
use std::time::Duration; |
|
|
|
use std::time::{Duration, Instant}; |
|
|
|
|
|
|
|
use ldap3::{DerefAliases, LdapConn, LdapConnAsync, Scope, SearchEntry, SearchOptions}; |
|
|
|
use ldap3::{DerefAliases, LdapConnAsync, Scope, SearchEntry, SearchOptions}; |
|
|
|
use tokio::prelude::*; |
|
|
|
use tokio::timer::Interval; |
|
|
|
use tokio_core::reactor::{Core, Handle}; |
|
|
@ -17,121 +17,16 @@ use crate::db::models::{Invitation, 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) |
|
|
|
} |
|
|
|
|
|
|
|
/* |
|
|
|
* /// Creates an LDAP connection, authenticating if necessary
|
|
|
|
* fn ldap_async_client(handle: &Handle, core: &Core) -> Result<LdapConnAsync, 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_uri = &format!("{}://{}:{}", scheme, host, port); |
|
|
|
* |
|
|
|
* let ldap = LdapConnAsync::new(ldap_uri, &handle)?.and_then(|ldap| { |
|
|
|
* 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(()) |
|
|
|
} |
|
|
|
|
|
|
|
fn invite_from_results(conn: DbConn, results: Vec<SearchEntry>) -> Result<(), Box<Error>> { |
|
|
|
let mail_field = CONFIG.ldap_mail_field(); |
|
|
|
for ldap_user in results { |
|
|
|
if let Some(user_email) = ldap_user.attrs[mail_field.as_str()].first() { |
|
|
|
match User::find_by_mail(user_email.as_str(), &conn) { |
|
|
|
Some(user) => println!("User already exists with email: {}", user_email), |
|
|
|
Some(_) => println!("User already exists with email: {}", user_email), |
|
|
|
None => { |
|
|
|
println!("New user, should try to add invite: {}", user_email); |
|
|
|
match Invitation::find_by_mail(user_email.as_str(), &conn) { |
|
|
|
Some(invite) => println!("User invite exists for {}", user_email), |
|
|
|
Some(_) => println!("User invite exists for {}", user_email), |
|
|
|
None => { |
|
|
|
println!("Creating new invite for {}", user_email); |
|
|
|
Invitation::new(user_email.clone()).save(&conn)?; |
|
|
@ -145,28 +40,6 @@ fn invite_from_results(conn: DbConn, results: Vec<SearchEntry>) -> Result<(), Bo |
|
|
|
Ok(()) |
|
|
|
} |
|
|
|
|
|
|
|
pub fn start_ldap_sync_old() -> Result<(), Box<Error>> { |
|
|
|
let duration = Duration::from_secs(2); |
|
|
|
let task = Interval::new_interval(duration) |
|
|
|
.take(10) |
|
|
|
.for_each(|instant| { |
|
|
|
let db_conn = db::get_dbconn().expect("Can't reach database"); |
|
|
|
match invite_from_ldap(db_conn) { |
|
|
|
Ok(_) => println!("Worked!"), |
|
|
|
Err(e) => { |
|
|
|
println!("{}", e); |
|
|
|
panic!("Failed!"); |
|
|
|
} |
|
|
|
}; |
|
|
|
Ok(()) |
|
|
|
}) |
|
|
|
.map_err(|e| panic!("interval errored: {:?}", e)); |
|
|
|
|
|
|
|
tokio::run(task); |
|
|
|
|
|
|
|
Ok(()) |
|
|
|
} |
|
|
|
|
|
|
|
fn new_ldap_client_async(handle: &Handle) -> Result<LdapConnAsync, Box<Error>> { |
|
|
|
let scheme = if CONFIG.ldap_ssl() { "ldaps" } else { "ldap" }; |
|
|
|
let host = CONFIG.ldap_host().unwrap(); |
|
|
@ -210,6 +83,7 @@ fn ldap_sync(handle: &Handle) -> Result<(), Box<Error>> { |
|
|
|
entries.push(SearchEntry::construct(result)); |
|
|
|
} |
|
|
|
let conn = db::get_dbconn().expect("Can't reach database"); |
|
|
|
// Can't figure out how to use this result
|
|
|
|
invite_from_results(conn, entries); |
|
|
|
Ok(()) |
|
|
|
}) |
|
|
@ -225,15 +99,18 @@ pub fn start_ldap_sync() -> Result<(), Box<Error>> { |
|
|
|
let mut core = Core::new().expect("Could not create core"); |
|
|
|
let handle = core.handle(); |
|
|
|
|
|
|
|
let task = Interval::new_interval(Duration::from_secs(5)) |
|
|
|
.take(10) |
|
|
|
.for_each(|instant| { |
|
|
|
let now = Instant::now(); |
|
|
|
let sync_interval = CONFIG.ldap_sync_interval().clone(); |
|
|
|
|
|
|
|
let task = Interval::new(now, Duration::from_secs(sync_interval)) |
|
|
|
.for_each(|_| { |
|
|
|
// Can't figure out how to get this error handled
|
|
|
|
ldap_sync(&handle); |
|
|
|
Ok(()) |
|
|
|
}) |
|
|
|
.map_err(|e| panic!("interval errored: {:?}", e)); |
|
|
|
|
|
|
|
core.run(task); |
|
|
|
core.run(task) |
|
|
|
}); |
|
|
|
|
|
|
|
Ok(()) |
|
|
|