ldap commit_1

This commit is contained in:
Mateusz Gruszczyński
2026-07-25 20:35:39 +02:00
parent ccde496e55
commit fcf7910f28
16 changed files with 608 additions and 13 deletions
+70
View File
@@ -1,5 +1,35 @@
use std::{env, net::IpAddr};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum AuthorizationType {
Local,
Ldap,
Ad,
}
impl AuthorizationType {
pub fn from_env() -> Result<Self, Box<dyn std::error::Error>> {
match env_var("AUTHORIZATION_TYPE", "local")
.trim()
.to_ascii_lowercase()
.as_str()
{
"local" => Ok(Self::Local),
"ldap" => Ok(Self::Ldap),
"ad" => Ok(Self::Ad),
_ => Err("AUTHORIZATION_TYPE must be one of: local, ldap, ad".into()),
}
}
pub fn as_str(self) -> &'static str {
match self {
Self::Local => "local",
Self::Ldap => "ldap",
Self::Ad => "ad",
}
}
}
#[derive(Debug, Clone)]
pub struct Config {
pub host: IpAddr,
@@ -20,6 +50,8 @@ pub struct Config {
pub frontend_log_level: String,
pub anonymous_access_token_ttl_days: i64,
pub user_session_ttl_days: i64,
pub authorization_type: AuthorizationType,
pub ldap: Option<crate::ldap_auth::LdapConfig>,
}
impl Config {
@@ -56,6 +88,34 @@ impl Config {
return Err("UPLOAD_MAX_SIZE_MB must be greater than 0".into());
}
let authorization_type = AuthorizationType::from_env()?;
let ldap = match authorization_type {
AuthorizationType::Local => None,
AuthorizationType::Ldap | AuthorizationType::Ad => {
let context = format!("AUTHORIZATION_TYPE={}", authorization_type.as_str());
let (default_filter, default_username_attribute) = match authorization_type {
AuthorizationType::Ldap => ("(uid={username})", "uid"),
AuthorizationType::Ad => (
"(|(sAMAccountName={username})(userPrincipalName={username}))",
"sAMAccountName",
),
AuthorizationType::Local => unreachable!(),
};
Some(crate::ldap_auth::LdapConfig {
url: required_nonempty_env("LDAP_URL", &context)?,
starttls: env_bool("LDAP_STARTTLS", false)?,
bind_dn: env::var("LDAP_BIND_DN").unwrap_or_default(),
bind_password: env::var("LDAP_BIND_PASSWORD").unwrap_or_default(),
base_dn: required_nonempty_env("LDAP_BASE_DN", &context)?,
user_filter: env_var("LDAP_USER_FILTER", default_filter),
username_attribute: env_var("LDAP_USERNAME_ATTRIBUTE", default_username_attribute),
email_attribute: env_var("LDAP_EMAIL_ATTRIBUTE", "mail"),
display_name_attribute: env_var("LDAP_DISPLAY_NAME_ATTRIBUTE", "displayName"),
organization: env_var("LDAP_ORGANIZATION", "organization"),
})
}
};
let smtp_host = std::env::var("SMTP_HOST")
.ok()
.filter(|v| !v.trim().is_empty());
@@ -95,6 +155,8 @@ impl Config {
frontend_log_level: env_log_level("FRONTEND_LOG_LEVEL", "warn")?,
anonymous_access_token_ttl_days,
user_session_ttl_days,
authorization_type,
ldap,
})
}
}
@@ -141,3 +203,11 @@ fn required_env(name: &str) -> Result<String, Box<dyn std::error::Error>> {
}
Ok(value)
}
fn required_nonempty_env(name: &str, context: &str) -> Result<String, Box<dyn std::error::Error>> {
let value = env::var(name).map_err(|_| format!("{name} is required when {context}"))?;
if value.trim().is_empty() {
return Err(format!("{name} cannot be empty when {context}").into());
}
Ok(value)
}