4 changed files with 95 additions and 8 deletions
@ -0,0 +1,89 @@ |
|||||
|
use crate::db; |
||||
|
use crate::CONFIG; |
||||
|
use ldap3::{DerefAliases, LdapConn, Scope, SearchEntry, SearchOptions}; |
||||
|
use std::collections::HashSet; |
||||
|
use std::error::Error; |
||||
|
use std::thread::sleep; |
||||
|
use std::time::Duration; |
||||
|
|
||||
|
pub fn launch_ldap_connector() { |
||||
|
let pool = db::init_pool(); |
||||
|
let conn = db::DbConn(pool.get().expect("Couldn't connect to DB.")); |
||||
|
let interval = Duration::from_secs(CONFIG.ldap_sync_interval()); |
||||
|
loop { |
||||
|
sync_from_ldap(&conn).expect("Couldn't sync users from LDAP."); |
||||
|
sleep(interval); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// Invite all LDAP users to Bitwarden
|
||||
|
fn sync_from_ldap(conn: &db::DbConn) -> Result<(), Box<Error>> { |
||||
|
match get_existing_users(&conn) { |
||||
|
Ok(existing_users) => { |
||||
|
let mut num_users = 0; |
||||
|
for ldap_user in search_entries()? { |
||||
|
// Safely get first email from list of emails in field
|
||||
|
if let Some(user_email) = ldap_user.attrs.get("mail").and_then(|l| (l.first())) { |
||||
|
if existing_users.contains(user_email) { |
||||
|
println!("User with email already exists: {}", user_email); |
||||
|
} else { |
||||
|
println!("Try to add user: {}", user_email); |
||||
|
// Add user
|
||||
|
db::models::User::new(user_email.to_string()).save(conn)?; |
||||
|
num_users = num_users + 1; |
||||
|
} |
||||
|
} else { |
||||
|
println!("Warning: Email field, mail, not found on user"); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// Maybe think about returning this value for some other use
|
||||
|
println!("Added {} user(s).", num_users); |
||||
|
} |
||||
|
Err(e) => { |
||||
|
println!("Error: Failed to get existing users from Bitwarden"); |
||||
|
return Err(e); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
Ok(()) |
||||
|
} |
||||
|
|
||||
|
/// Retrieves search results from ldap
|
||||
|
fn search_entries() -> Result<Vec<SearchEntry>, Box<Error>> { |
||||
|
let ldap = LdapConn::new(CONFIG.ldap_host().as_str())?; |
||||
|
ldap.simple_bind(CONFIG.ldap_bind_dn().as_str(), CONFIG.ldap_bind_password().as_str())?; |
||||
|
|
||||
|
let fields = vec!["uid", "givenname", "sn", "cn", "mail"]; |
||||
|
|
||||
|
// TODO: Something something error handling
|
||||
|
let (results, _res) = ldap |
||||
|
.with_search_options(SearchOptions::new().deref(DerefAliases::Always)) |
||||
|
.search( |
||||
|
CONFIG.ldap_search_base_dn().as_str(), |
||||
|
Scope::Subtree, |
||||
|
CONFIG.ldap_search_filter().as_str(), |
||||
|
fields, |
||||
|
)? |
||||
|
.success()?; |
||||
|
|
||||
|
// Build list of entries
|
||||
|
let mut entries = Vec::new(); |
||||
|
for result in results { |
||||
|
entries.push(SearchEntry::construct(result)); |
||||
|
} |
||||
|
|
||||
|
Ok(entries) |
||||
|
} |
||||
|
|
||||
|
/// Creates set of email addresses for users that already exist in Bitwarden
|
||||
|
fn get_existing_users(conn: &db::DbConn) -> Result<HashSet<String>, Box<Error>> { |
||||
|
let all_users = db::models::User::get_all(conn); |
||||
|
|
||||
|
let mut user_emails = HashSet::with_capacity(all_users.len()); |
||||
|
for user in all_users { |
||||
|
user_emails.insert(user.email); |
||||
|
} |
||||
|
|
||||
|
Ok(user_emails) |
||||
|
} |
Loading…
Reference in new issue