deadpool_ldap3/
lib.rs

1pub mod config;
2
3use deadpool::managed::{Metrics, RecycleError, RecycleResult};
4use deadpool::{managed, Runtime};
5use ldap3::{Ldap, LdapConnAsync, LdapError};
6
7use crate::config::{Config, LdapConfigError};
8
9deadpool::managed_reexports!(
10    "ldap",
11    Manager,
12    managed::Object<Manager>,
13    LdapError,
14    LdapConfigError
15);
16
17pub struct Manager {
18    /// LDAP addr
19    pub url: String,
20    /// Manager Account
21    pub bind_dn: Option<String>,
22    /// Manager Password
23    pub bind_password: Option<String>,
24    /// Runtime, Use deadpool runtime
25    pub runtime: Runtime,
26}
27
28impl Manager {
29    #[must_use]
30    pub fn from_config(config: &Config, runtime: Runtime) -> Self {
31        Self {
32            url: config.url.clone(),
33            bind_dn: config.bind_dn.clone(),
34            bind_password: config.bind_password.clone(),
35            runtime,
36        }
37    }
38}
39
40pub type LdapConnection = Ldap;
41
42impl managed::Manager for Manager {
43    type Type = LdapConnection;
44    type Error = LdapError;
45
46    /// create conn
47    async fn create(&self) -> Result<LdapConnection, LdapError> {
48        let (conn, mut ldap) = LdapConnAsync::new(&self.url).await?;
49        match self.runtime {
50            #[cfg(feature = "rt_tokio_1")]
51            Runtime::Tokio1 => {
52                tokio::spawn(async move { conn.drive().await });
53            }
54            #[cfg(feature = "rt_async-std_1")]
55            Runtime::AsyncStd1 => {
56                async_std::task::spawn(async move { conn.drive().await });
57            }
58            #[allow(unreachable_patterns)]
59            _ => unreachable!(),
60        };
61        if let (Some(bind_dn), Some(bind_password)) = (&self.bind_dn, &self.bind_password) {
62            ldap.simple_bind(bind_dn, bind_password).await?.success()?;
63        }
64        Ok(ldap)
65    }
66
67    /// recycle conn
68    async fn recycle(&self, ldap: &mut LdapConnection, _: &Metrics) -> RecycleResult<LdapError> {
69        // re
70        if let (Some(bind_dn), Some(bind_password)) = (&self.bind_dn, &self.bind_password) {
71            ldap.simple_bind(bind_dn, bind_password).await?.success()?;
72        }
73        // check if the LDAP connection is closed
74        if ldap.is_closed() {
75            Err(RecycleError::message("ldap connection is closed"))
76        } else {
77            Ok(())
78        }
79    }
80}
81
82#[tokio::test]
83async fn test_ldap() {
84    let cfg = Config {
85        url: "ldap://127.0.0.1:389".to_string(),
86        bind_dn: Some("cn=admin,dc=demo,dc=com".to_string()),
87        bind_password: Some("123456".to_string()),
88        pool: None,
89    };
90    let pool = cfg.create_pool(Runtime::Tokio1).unwrap();
91    let mut a = pool.get().await.unwrap();
92    a.simple_bind("admin", "123456").await.unwrap();
93}