pub struct LdapClient { /* private fields */ }Expand description
High-level LDAP client wrapper ontop of ldap3 crate. This wrapper provides a high-level interface to perform LDAP operations including authentication, search, update, delete
Implementations§
Source§impl LdapClient
impl LdapClient
Source§impl LdapClient
impl LdapClient
Sourcepub fn get_inner(&self) -> Ldap
👎Deprecated: This abstraction leakage will be removed in a future release.
Use the provided methods instead. If something’s missing, open an issue in github.
pub fn get_inner(&self) -> Ldap
Returns the ldap3 client
Sourcepub async fn unbind(self) -> Result<(), Error>
pub async fn unbind(self) -> Result<(), Error>
End the LDAP connection.
Caution advised!
This will close the connection for all clones of this client as well, including open streams. So make sure that you’re really good to close.
Closing an LDAP connection with an unbind is a curtesy. It’s fine to skip it, and because of the async hurdless outlined above, I would perhaps even recommend it.
Sourcepub async fn authenticate(
&mut self,
base: &str,
uid: &str,
password: &str,
filter: Box<dyn Filter>,
) -> Result<(), Error>
pub async fn authenticate( &mut self, base: &str, uid: &str, password: &str, filter: Box<dyn Filter>, ) -> Result<(), Error>
The user is authenticated by searching for the user in the LDAP server. The search is performed using the provided filter. The filter should be a filter that matches a single user.
§Arguments
base- The base DN to search for the useruid- The uid of the userpassword- The password of the userfilter- The filter to search for the user
§Returns
Result<(), Error>- Returns an error if the authentication fails
§Example
use simple_ldap::{
LdapClient, LdapConfig,
filter::EqFilter
};
use url::Url;
#[tokio::main]
async fn main(){
let ldap_config = LdapConfig {
bind_dn: String::from("cn=manager"),
bind_password: String::from("password"),
ldap_url: Url::parse("ldaps://localhost:1389/dc=example,dc=com").unwrap(),
dn_attribute: None,
connection_settings: None
};
let mut client = LdapClient::new(ldap_config).await.unwrap();
let name_filter = EqFilter::from("cn".to_string(), "Sam".to_string());
let result = client.authenticate("", "Sam", "password", Box::new(name_filter)).await;
}Sourcepub async fn search<'a, F, A, S, T>(
&mut self,
base: &str,
scope: Scope,
filter: &F,
attributes: A,
) -> Result<T, Error>
pub async fn search<'a, F, A, S, T>( &mut self, base: &str, scope: Scope, filter: &F, attributes: A, ) -> Result<T, Error>
Search a single value from the LDAP server. The search is performed using the provided filter. The filter should be a filter that matches a single record. if the filter matches multiple users, an error is returned. This operation will treat all the attributes as single-valued, silently ignoring the possible extra values.
§Arguments
base- The base DN to search for the userscope- The scope of the searchfilter- The filter to search for the userattributes- The attributes to return from the search
§Returns
Result<T, Error>- The result will be mapped to a struct of type T
§Example
use simple_ldap::{
LdapClient, LdapConfig,
filter::EqFilter,
ldap3::Scope
};
use url::Url;
use serde::Deserialize;
#[derive(Debug, Deserialize)]
struct User {
uid: String,
cn: String,
sn: String,
}
#[tokio::main]
async fn main(){
let ldap_config = LdapConfig {
bind_dn: String::from("cn=manager"),
bind_password: String::from("password"),
ldap_url: Url::parse("ldaps://localhost:1389/dc=example,dc=com").unwrap(),
dn_attribute: None,
connection_settings: None
};
let mut client = LdapClient::new(ldap_config).await.unwrap();
let name_filter = EqFilter::from("cn".to_string(), "Sam".to_string());
let user_result: User = client
.search(
"ou=people,dc=example,dc=com",
Scope::OneLevel,
&name_filter,
vec!["cn", "sn", "uid"],
).await
.unwrap();
}Sourcepub async fn search_multi_valued<T: for<'a> Deserialize<'a>>(
&mut self,
base: &str,
scope: Scope,
filter: &impl Filter,
attributes: &Vec<&str>,
) -> Result<T, Error>
pub async fn search_multi_valued<T: for<'a> Deserialize<'a>>( &mut self, base: &str, scope: Scope, filter: &impl Filter, attributes: &Vec<&str>, ) -> Result<T, Error>
Search a single value from the LDAP server. The search is performed using the provided filter. The filter should be a filter that matches a single record. if the filter matches multiple users, an error is returned. This operatrion is useful when records has multi-valued attributes.
§Arguments
base- The base DN to search for the userscope- The scope of the searchfilter- The filter to search for the userattributes- The attributes to return from the search
§Returns
Result<T, Error>- The result will be mapped to a struct of type T
§Example
use simple_ldap::{
LdapClient, LdapConfig,
filter::EqFilter,
ldap3::Scope
};
use url::Url;
use serde::Deserialize;
#[derive(Debug, Deserialize)]
struct TestMultiValued {
key1: Vec<String>,
key2: Vec<String>,
}
#[tokio::main]
async fn main(){
let ldap_config = LdapConfig {
bind_dn: String::from("cn=manager"),
bind_password: String::from("password"),
ldap_url: Url::parse("ldaps://localhost:1389/dc=example,dc=com").unwrap(),
dn_attribute: None,
connection_settings: None
};
let mut client = LdapClient::new(ldap_config).await.unwrap();
let name_filter = EqFilter::from("cn".to_string(), "Sam".to_string());
let user_result = client.search_multi_valued::<TestMultiValued>(
"",
Scope::OneLevel,
&name_filter,
&vec!["cn", "sn", "uid"]
).await;
}Sourcepub async fn streaming_search<'a, F, A, S>(
&'a mut self,
base: &str,
scope: Scope,
filter: &F,
attributes: A,
) -> Result<impl Stream<Item = Result<Record, Error>> + use<'a, F, A, S>, Error>
pub async fn streaming_search<'a, F, A, S>( &'a mut self, base: &str, scope: Scope, filter: &F, attributes: A, ) -> Result<impl Stream<Item = Result<Record, Error>> + use<'a, F, A, S>, Error>
This method is used to search multiple records from the LDAP server. The search is performed using the provided filter. Method will return a Stream. The stream will lazily fetch the results, resulting in a smaller memory footprint.
You might also want to take a look at [streaming_search_paged()].
§Arguments
base- The base DN to search for the userscope- The scope of the searchfilter- The filter to search for the userattributes- The attributes to return from the search
§Returns
A stream that can be used to iterate through the search results.
§Blocking drop caveat
Dropping this stream may issue blocking network requests to cancel the search. Running the stream to it’s end will minimize the chances of this happening. You should take this into account if latency is critical to your application.
We’re waiting for AsyncDrop for implementing this properly.
§Example
use simple_ldap::{
LdapClient, LdapConfig,
filter::EqFilter,
ldap3::Scope
};
use url::Url;
use serde::Deserialize;
use futures::StreamExt;
#[derive(Deserialize, Debug)]
struct User {
uid: String,
cn: String,
sn: String,
}
#[tokio::main]
async fn main(){
let ldap_config = LdapConfig {
bind_dn: String::from("cn=manager"),
bind_password: String::from("password"),
ldap_url: Url::parse("ldaps://localhost:1389/dc=example,dc=com").unwrap(),
dn_attribute: None,
connection_settings: None
};
let mut client = LdapClient::new(ldap_config).await.unwrap();
let name_filter = EqFilter::from(String::from("cn"), String::from("Sam"));
let attributes = vec!["cn", "sn", "uid"];
let stream = client.streaming_search(
"",
Scope::OneLevel,
&name_filter,
attributes
).await.unwrap();
// The returned stream is not Unpin, so you may need to pin it to use certain operations,
// such as next() below.
let mut pinned_steam = Box::pin(stream);
while let Some(result) = pinned_steam.next().await {
match result {
Ok(element) => {
let user: User = element.to_record().unwrap();
println!("User: {:?}", user);
}
Err(err) => {
println!("Error: {:?}", err);
}
}
}
}Sourcepub async fn streaming_search_paged<'a, F, A, S>(
&'a mut self,
base: &str,
scope: Scope,
filter: &F,
attributes: A,
page_size: i32,
) -> Result<impl Stream<Item = Result<Record, Error>> + use<'a, F, A, S>, Error>
pub async fn streaming_search_paged<'a, F, A, S>( &'a mut self, base: &str, scope: Scope, filter: &F, attributes: A, page_size: i32, ) -> Result<impl Stream<Item = Result<Record, Error>> + use<'a, F, A, S>, Error>
This method is used to search multiple records from the LDAP server and results will be paginated. Method will return a Stream. The stream will lazily fetch batches of results resulting in a smaller memory footprint.
This is the recommended search method, especially if you don’t know that the result set is going to be small.
§Arguments
base- The base DN to search for the userscope- The scope of the searchfilter- The filter to search for the userpage_size- The maximum number of records in a pageattributes- The attributes to return from the search
§Returns
A stream that can be used to iterate through the search results.
§Blocking drop caveat
Dropping this stream may issue blocking network requests to cancel the search. Running the stream to it’s end will minimize the chances of this happening. You should take this into account if latency is critical to your application.
We’re waiting for AsyncDrop for implementing this properly.
§Example
use simple_ldap::{
LdapClient, LdapConfig,
filter::EqFilter,
ldap3::Scope
};
use url::Url;
use serde::Deserialize;
use futures::{StreamExt, TryStreamExt};
#[derive(Deserialize, Debug)]
struct User {
uid: String,
cn: String,
sn: String,
}
#[tokio::main]
async fn main(){
let ldap_config = LdapConfig {
bind_dn: String::from("cn=manager"),
bind_password: String::from("password"),
ldap_url: Url::parse("ldaps://localhost:1389/dc=example,dc=com").unwrap(),
dn_attribute: None,
connection_settings: None
};
let mut client = LdapClient::new(ldap_config).await.unwrap();
let name_filter = EqFilter::from(String::from("cn"), String::from("Sam"));
let attributes = vec!["cn", "sn", "uid"];
let stream = client.streaming_search_paged(
"",
Scope::OneLevel,
&name_filter,
attributes,
200 // The pagesize
).await.unwrap();
// Map the search results to User type.
stream.and_then(async |record| record.to_record())
// Do something with the Users concurrently.
.try_for_each(async |user: User| {
println!("User: {:?}", user);
Ok(())
})
.await
.unwrap();
}Sourcepub async fn create(
&mut self,
uid: &str,
base: &str,
data: Vec<(&str, HashSet<&str>)>,
) -> Result<(), Error>
pub async fn create( &mut self, uid: &str, base: &str, data: Vec<(&str, HashSet<&str>)>, ) -> Result<(), Error>
Create a new record in the LDAP server. The record will be created in the provided base DN.
§Arguments
uid- The uid of the recordbase- The base DN to create the recorddata- The attributes of the record
§Returns
Result<(), Error>- Returns an error if the record creation fails
§Example
use simple_ldap::{LdapClient, LdapConfig};
use url::Url;
use std::collections::HashSet;
#[tokio::main]
async fn main(){
let ldap_config = LdapConfig {
bind_dn: String::from("cn=manager"),
bind_password: String::from("password"),
ldap_url: Url::parse("ldaps://localhost:1389/dc=example,dc=com").unwrap(),
dn_attribute: None,
connection_settings: None
};
let mut client = LdapClient::new(ldap_config).await.unwrap();
let data = vec![
( "objectClass",HashSet::from(["organizationalPerson", "inetorgperson", "top", "person"]),),
("uid",HashSet::from(["bd9b91ec-7a69-4166-bf67-cc7e553b2fd9"]),),
("cn", HashSet::from(["Kasun"])),
("sn", HashSet::from(["Ranasingh"])),
];
let result = client.create("bd9b91ec-7a69-4166-bf67-cc7e553b2fd9", "ou=people,dc=example,dc=com", data).await;
}Sourcepub async fn update(
&mut self,
uid: &str,
base: &str,
data: Vec<Mod<&str>>,
new_uid: Option<&str>,
) -> Result<(), Error>
pub async fn update( &mut self, uid: &str, base: &str, data: Vec<Mod<&str>>, new_uid: Option<&str>, ) -> Result<(), Error>
Update a record in the LDAP server. The record will be updated in the provided base DN.
§Arguments
uid- The uid of the recordbase- The base DN to update the recorddata- The attributes of the recordnew_uid- The new uid of the record. If the new uid is provided, the uid of the record will be updated.
§Returns
Result<(), Error>- Returns an error if the record update fails
§Example
use simple_ldap::{
LdapClient, LdapConfig,
ldap3::Mod
};
use url::Url;
use std::collections::HashSet;
#[tokio::main]
async fn main(){
let ldap_config = LdapConfig {
bind_dn: String::from("cn=manager"),
bind_password: String::from("password"),
ldap_url: Url::parse("ldaps://localhost:1389/dc=example,dc=com").unwrap(),
dn_attribute: None,
connection_settings: None
};
let mut client = LdapClient::new(ldap_config).await.unwrap();
let data = vec![
Mod::Replace("cn", HashSet::from(["Jhon_Update"])),
Mod::Replace("sn", HashSet::from(["Eliet_Update"])),
];
let result = client.update(
"e219fbc0-6df5-4bc3-a6ee-986843bb157e",
"ou=people,dc=example,dc=com",
data,
None
).await;
}Sourcepub async fn delete(&mut self, uid: &str, base: &str) -> Result<(), Error>
pub async fn delete(&mut self, uid: &str, base: &str) -> Result<(), Error>
Delete a record in the LDAP server. The record will be deleted in the provided base DN.
§Arguments
uid- The uid of the recordbase- The base DN to delete the record
§Returns
Result<(), Error>- Returns an error if the record delete fails
§Example
use simple_ldap::{LdapClient, LdapConfig};
use url::Url;
#[tokio::main]
async fn main(){
let ldap_config = LdapConfig {
bind_dn: String::from("cn=manager"),
bind_password: String::from("password"),
ldap_url: Url::parse("ldaps://localhost:1389/dc=example,dc=com").unwrap(),
dn_attribute: None,
connection_settings: None
};
let mut client = LdapClient::new(ldap_config).await.unwrap();
let result = client.delete("e219fbc0-6df5-4bc3-a6ee-986843bb157e", "ou=people,dc=example,dc=com").await;
}Sourcepub async fn create_group(
&mut self,
group_name: &str,
group_ou: &str,
description: &str,
) -> Result<(), Error>
pub async fn create_group( &mut self, group_name: &str, group_ou: &str, description: &str, ) -> Result<(), Error>
Create a new group in the LDAP server. The group will be created in the provided base DN.
§Arguments
group_name- The name of the groupgroup_ou- The ou of the groupdescription- The description of the group
§Returns
Result<(), Error>- Returns an error if the group creation fails
§Example
use simple_ldap::{LdapClient, LdapConfig};
use url::Url;
#[tokio::main]
async fn main(){
let ldap_config = LdapConfig {
bind_dn: String::from("cn=manager"),
bind_password: String::from("password"),
ldap_url: Url::parse("ldaps://localhost:1389/dc=example,dc=com").unwrap(),
dn_attribute: None,
connection_settings: None
};
let mut client = LdapClient::new(ldap_config).await.unwrap();
let result = client.create_group("test_group", "ou=groups,dc=example,dc=com", "test group").await;
}Sourcepub async fn add_users_to_group(
&mut self,
users: Vec<&str>,
group_dn: &str,
) -> Result<(), Error>
pub async fn add_users_to_group( &mut self, users: Vec<&str>, group_dn: &str, ) -> Result<(), Error>
Add users to a group in the LDAP server. The group will be updated in the provided base DN.
§Arguments
users- The list of users to add to the groupgroup_dn- The dn of the group
§Returns
Result<(), Error>- Returns an error if failed to add users to the group
§Example
use simple_ldap::{LdapClient, LdapConfig};
use url::Url;
#[tokio::main]
async fn main(){
let ldap_config = LdapConfig {
bind_dn: String::from("cn=manager"),
bind_password: String::from("password"),
ldap_url: Url::parse("ldaps://localhost:1389/dc=example,dc=com").unwrap(),
dn_attribute: None,
connection_settings: None
};
let mut client = LdapClient::new(ldap_config).await.unwrap();
let result = client.add_users_to_group(
vec!["uid=bd9b91ec-7a69-4166-bf67-cc7e553b2fd9,ou=people,dc=example,dc=com"],
"cn=test_group,ou=groups,dc=example,dc=com").await;
}Sourcepub async fn get_members<'a, A, S, T>(
&mut self,
group_dn: &str,
base_dn: &str,
scope: Scope,
attributes: A,
) -> Result<Vec<T>, Error>
pub async fn get_members<'a, A, S, T>( &mut self, group_dn: &str, base_dn: &str, scope: Scope, attributes: A, ) -> Result<Vec<T>, Error>
Get users of a group in the LDAP server. The group will be searched in the provided base DN.
§Arguments
group_dn- The dn of the groupbase_dn- The base dn to search for the usersscope- The scope of the searchattributes- The attributes to return from the search
§Returns
Result<Vec<T>, Error>- Returns a vector of structs of type T
§Example
use simple_ldap::{
LdapClient, LdapConfig,
ldap3::Scope
};
use url::Url;
use serde::Deserialize;
#[derive(Debug, Deserialize)]
struct User {
uid: String,
cn: String,
sn: String,
}
#[tokio::main]
async fn main(){
let ldap_config = LdapConfig {
bind_dn: String::from("cn=manager"),
bind_password: String::from("password"),
ldap_url: Url::parse("ldaps://localhost:1389/dc=example,dc=com").unwrap(),
dn_attribute: None,
connection_settings: None
};
let mut client = LdapClient::new(ldap_config).await.unwrap();
let members: Vec<User> = client.get_members(
"cn=test_group,ou=groups,dc=example,dc=com",
"ou=people,dc=example,dc=com",
Scope::OneLevel,
vec!["cn", "sn", "uid"]
).await
.unwrap();
}Sourcepub async fn remove_users_from_group(
&mut self,
group_dn: &str,
users: Vec<&str>,
) -> Result<(), Error>
pub async fn remove_users_from_group( &mut self, group_dn: &str, users: Vec<&str>, ) -> Result<(), Error>
Remove users from a group in the LDAP server. The group will be updated in the provided base DN. This method will remove all the users provided from the group.
§Arguments
group_dn- The dn of the groupusers- The list of users to remove from the group
§Returns
Result<(), Error>- Returns an error if failed to remove users from the group
§Example
use simple_ldap::{LdapClient, LdapConfig};
use url::Url;
use std::collections::HashSet;
#[tokio::main]
async fn main(){
let ldap_config = LdapConfig {
bind_dn: String::from("cn=manager"),
bind_password: String::from("password"),
ldap_url: Url::parse("ldaps://localhost:1389/dc=example,dc=com").unwrap(),
dn_attribute: None,
connection_settings: None
};
let mut client = LdapClient::new(ldap_config).await.unwrap();
let result = client.remove_users_from_group("cn=test_group,ou=groups,dc=example,dc=com",
vec!["uid=bd9b91ec-7a69-4166-bf67-cc7e553b2fd9,ou=people,dc=example,dc=com"]).await;
}Sourcepub async fn get_associtated_groups(
&mut self,
group_ou: &str,
user_dn: &str,
) -> Result<Vec<String>, Error>
pub async fn get_associtated_groups( &mut self, group_ou: &str, user_dn: &str, ) -> Result<Vec<String>, Error>
Get the groups associated with a user in the LDAP server. The user will be searched in the provided base DN.
§Arguments
group_ou- The ou to search for the groupsuser_dn- The dn of the user
§Returns
Result<Vec<String>, Error>- Returns a vector of group names
§Example
use simple_ldap::{LdapClient, LdapConfig};
use url::Url;
#[tokio::main]
async fn main(){
let ldap_config = LdapConfig {
bind_dn: String::from("cn=manager"),
bind_password: String::from("password"),
ldap_url: Url::parse("ldaps://localhost:1389/dc=example,dc=com").unwrap(),
dn_attribute: None,
connection_settings: None
};
let mut client = LdapClient::new(ldap_config).await.unwrap();
let result = client.get_associtated_groups("ou=groups,dc=example,dc=com",
"uid=bd9b91ec-7a69-4166-bf67-cc7e553b2fd9,ou=people,dc=example,dc=com").await;
}Trait Implementations§
Source§impl Clone for LdapClient
impl Clone for LdapClient
Source§fn clone(&self) -> LdapClient
fn clone(&self) -> LdapClient
1.0.0 · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreAuto Trait Implementations§
impl Freeze for LdapClient
impl RefUnwindSafe for LdapClient
impl Send for LdapClient
impl Sync for LdapClient
impl Unpin for LdapClient
impl UnwindSafe for LdapClient
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more