Skip to content

Commit

Permalink
Add support for LDAP client
Browse files Browse the repository at this point in the history
  • Loading branch information
photino committed Jan 10, 2025
1 parent 9a26eff commit 4aaba29
Show file tree
Hide file tree
Showing 14 changed files with 98 additions and 22 deletions.
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
MIT License

Copyright (c) 2022-2024 Zan Pan
Copyright (c) 2022-2025 Zan Pan

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
8 changes: 7 additions & 1 deletion crates/zino-auth/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
name = "zino-auth"
description = "Authentication and authorization for zino."
version = "0.3.0"
version = "0.3.1"
rust-version = "1.80"
edition = "2021"
license = "MIT"
Expand All @@ -15,6 +15,7 @@ readme = "README.md"
[package.metadata.docs.rs]
features = [
"jwt",
"ldap",
"oidc",
"opa",
"sqids",
Expand All @@ -25,6 +26,7 @@ rustdoc-args = ["--cfg", "docsrs"]
[features]
crypto-sm = ["zino-core/crypto-sm"]
jwt = ["dep:jwt-simple", "regorus?/jwt"]
ldap = ["dep:simple-ldap"]
oidc = ["dep:rauthy-client"]
opa = ["regorus"]
sqids = ["dep:sqids"]
Expand All @@ -42,6 +44,10 @@ optional = true
default-features = false
features = ["pure-rust"]

[dependencies.simple-ldap]
version = "2.1.1"
optional = true

[dependencies.rauthy-client]
version = "0.6.1"
optional = true
Expand Down
1 change: 1 addition & 0 deletions crates/zino-auth/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ The following optional features are available:
|----------------------|--------------------------------------------------------|----------|
| `crypto-sm` | Enables China's Standards of Encryption Algorithms. | No |
| `jwt` | Enables the support for JSON Web Token. | No |
| `ldap` | Enables the support for LDAP. | No |
| `oidc` | Enables the support for OIDC via [`rauthy`]. | No |
| `opa` | Enables the support for OPA via [`regorus`]. | No |
| `sqids` | Enables the support for [`sqids`]. | No |
Expand Down
63 changes: 63 additions & 0 deletions crates/zino-auth/src/ldap_client.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
use simple_ldap::pool::{LdapConfig, LdapPool};
use std::sync::OnceLock;
use zino_core::{
application::{Agent, Application, Plugin},
bail,
error::Error,
extension::TomlTableExt,
state::State,
};

/// The LDAP client.
#[derive(Debug, Clone, Copy)]
pub struct LdapClient;

impl LdapClient {
/// Initializes the LDAP pool.
pub fn init() -> Plugin {
let loader = Box::pin(async {
let Some(config) = Agent::config().get_table("ldap") else {
bail!("`ldap` config should be specified");
};
let Some(url) = config.get_str("url") else {
bail!("`ldap.url` should be specified");
};
let Some(account) = config.get_str("account") else {
bail!("`ldap.account` should be specified");
};
let Some(password) = State::decrypt_password(config) else {
bail!("`ldap.password` should be specified");
};
let ldap_config = LdapConfig {
ldap_url: url.to_owned(),
bind_dn: format!("cn={account}"),
bind_pw: password.into_owned(),
pool_size: config.get_usize("pool-size").unwrap_or(10),
dn_attribute: None,
};
let ldap_pool = simple_ldap::pool::build_connection_pool(&ldap_config).await;
if LDAP_POOL.set(ldap_pool).is_err() {
tracing::error!("fail to initialize the LDAP pool");
}
Ok(())
});
let mut plugin = Plugin::new("ldap-client");
plugin.set_loader(loader);
plugin
}

/// Returns an existing LDAP connection from the pool or creates a new one if required.
#[inline]
pub async fn get_connection() -> Result<simple_ldap::LdapClient, simple_ldap::Error> {
if let Some(pool) = LDAP_POOL.get() {
pool.get_connection().await
} else {
Err(simple_ldap::Error::NotFound(
"LDAP pool is not initialized".to_owned(),
))
}
}
}

/// Shared LDAP pool.
static LDAP_POOL: OnceLock<LdapPool> = OnceLock::new();
5 changes: 5 additions & 0 deletions crates/zino-auth/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ pub use user_session::UserSession;

#[cfg(feature = "jwt")]
mod jwt_claims;
#[cfg(feature = "ldap")]
mod ldap_client;
#[cfg(feature = "oidc")]
mod rauthy_client;
#[cfg(feature = "opa")]
Expand All @@ -31,6 +33,9 @@ mod rego_engine;
#[cfg(feature = "jwt")]
pub use jwt_claims::{default_time_tolerance, default_verification_options, JwtClaims, JwtHmacKey};

#[cfg(feature = "ldap")]
pub use ldap_client::LdapClient;

#[cfg(feature = "oidc")]
pub use rauthy_client::RauthyClient;

Expand Down
2 changes: 1 addition & 1 deletion crates/zino-derive/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
name = "zino-derive"
description = "Derived traits for zino."
version = "0.29.0"
version = "0.29.1"
rust-version = "1.80"
edition = "2021"
license = "MIT"
Expand Down
13 changes: 9 additions & 4 deletions crates/zino-derive/src/model_accessor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -193,10 +193,15 @@ pub(super) fn parse_token_stream(input: DeriveInput) -> TokenStream {
});
}
}
if auto_rename && name.ends_with("_id") {
let value = name.trim_end_matches("_id").to_owned();
let populated_field = [&name, "_populated"].concat();
populated_field_mappings.insert(populated_field, value);
if auto_rename {
if name.ends_with("_id") {
let value = name.trim_end_matches("_id").to_owned();
let populated_field = [&name, "_populated"].concat();
populated_field_mappings.insert(populated_field, value);
} else if parser::check_vec_type(type_name) {
let populated_field = [&name, "_populated"].concat();
populated_field_mappings.insert(populated_field, name.clone());
}
}
}
"fetch_as" => {
Expand Down
2 changes: 1 addition & 1 deletion crates/zino-http/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ optional = true

[dependencies.zino-auth]
path = "../zino-auth"
version = "0.3.0"
version = "0.3.1"
optional = true

[dependencies.zino-channel]
Expand Down
6 changes: 3 additions & 3 deletions crates/zino-model/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
name = "zino-model"
description = "Domain models for zino."
version = "0.29.0"
version = "0.29.1"
rust-version = "1.80"
edition = "2021"
license = "MIT"
Expand Down Expand Up @@ -49,7 +49,7 @@ features = ["derive"]

[dependencies.zino-auth]
path = "../zino-auth"
version = "0.3.0"
version = "0.3.1"
features = ["jwt"]

[dependencies.zino-core]
Expand All @@ -59,7 +59,7 @@ features = ["validator-email"]

[dependencies.zino-derive]
path = "../zino-derive"
version = "0.29.0"
version = "0.29.1"

[dependencies.zino-orm]
path = "../zino-orm"
Expand Down
4 changes: 1 addition & 3 deletions crates/zino/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ features = [
"axum",
"i18n",
"jwt",
"oidc",
"opa",
"orm",
]
Expand All @@ -39,7 +38,6 @@ jwt = ["auth", "zino-auth/jwt", "zino-http?/jwt"]
logger = ["zino-core/tracing-log", "zino-core/tracing-subscriber"]
metrics = ["zino-core/metrics", "zino-http?/metrics", "zino-storage/metrics"]
ntex = ["dep:zino-http", "dep:zino-ntex", "dep:zino-openapi"]
oidc = ["auth", "zino-auth/oidc"]
opa = ["auth", "zino-auth/opa"]
orm = [
"zino-orm",
Expand All @@ -60,7 +58,7 @@ optional = true

[dependencies.zino-auth]
path = "../zino-auth"
version = "0.3.0"
version = "0.3.1"
optional = true

[dependencies.zino-axum]
Expand Down
2 changes: 0 additions & 2 deletions crates/zino/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,6 @@ The following optional features are available:
| `logger` | Enables the default logger. | Yes |
| `metrics` | Enables the [`metrics`] exporter. | No |
| `ntex` | Enables the integration with [`ntex`]. | No |
| `oidc` | Enables the support for OIDC via [`rauthy`]. | No |
| `opa` | Enables the support for OPA via [`regorus`]. | No |
| `orm` | Enables the ORM for MySQL, PostgreSQL or **SQLite**. | No |
| `view` | Enables the HTML template rendering. | No |
Expand All @@ -71,7 +70,6 @@ The following optional features are available:
[`sqlx`]: https://crates.io/crates/sqlx
[`tracing`]: https://crates.io/crates/tracing
[`metrics`]: https://crates.io/crates/metrics
[`rauthy`]: https://crates.io/crates/rauthy-client
[`regorus`]: https://crates.io/crates/regorus
[`actix-web`]: https://crates.io/crates/actix-web
[`axum`]: https://crates.io/crates/axum
Expand Down
4 changes: 2 additions & 2 deletions examples/actix-app/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,11 @@ features = ["env-filter"]

[dependencies.zino-derive]
path = "../../crates/zino-derive"
version = "0.29.0"
version = "0.29.1"

[dependencies.zino-model]
path = "../../crates/zino-model"
version = "0.29.0"
version = "0.29.1"

[dependencies.zino-orm]
path = "../../crates/zino-orm"
Expand Down
4 changes: 2 additions & 2 deletions examples/axum-app/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,11 @@ features = ["env-filter", "validator-email"]

[dependencies.zino-derive]
path = "../../crates/zino-derive"
version = "0.29.0"
version = "0.29.1"

[dependencies.zino-model]
path = "../../crates/zino-model"
version = "0.29.0"
version = "0.29.1"

[dependencies.zino-orm]
path = "../../crates/zino-orm"
Expand Down
4 changes: 2 additions & 2 deletions examples/ntex-app/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,11 @@ features = ["env-filter"]

[dependencies.zino-derive]
path = "../../crates/zino-derive"
version = "0.29.0"
version = "0.29.1"

[dependencies.zino-model]
path = "../../crates/zino-model"
version = "0.29.0"
version = "0.29.1"

[dependencies.zino-orm]
path = "../../crates/zino-orm"
Expand Down

0 comments on commit 4aaba29

Please sign in to comment.