mirror of
https://forgejo.ellis.link/continuwuation/continuwuity.git
synced 2026-05-26 20:49:55 +00:00
fix: Only sync LDAP admin status when admin_filter is configured
Closes #1307
This commit is contained in:
@@ -0,0 +1 @@
|
|||||||
|
LDAP-enabled servers will no longer have all admins demoted when LDAP-controlled admins are not configured. Contributed by @Jade
|
||||||
@@ -107,7 +107,7 @@ pub(super) async fn ldap_login(
|
|||||||
) -> Result<OwnedUserId> {
|
) -> Result<OwnedUserId> {
|
||||||
let (user_dn, is_ldap_admin) = match services.config.ldap.bind_dn.as_ref() {
|
let (user_dn, is_ldap_admin) = match services.config.ldap.bind_dn.as_ref() {
|
||||||
| Some(bind_dn) if bind_dn.contains("{username}") =>
|
| Some(bind_dn) if bind_dn.contains("{username}") =>
|
||||||
(bind_dn.replace("{username}", lowercased_user_id.localpart()), false),
|
(bind_dn.replace("{username}", lowercased_user_id.localpart()), None),
|
||||||
| _ => {
|
| _ => {
|
||||||
debug!("Searching user in LDAP");
|
debug!("Searching user in LDAP");
|
||||||
|
|
||||||
@@ -144,12 +144,16 @@ pub(super) async fn ldap_login(
|
|||||||
.await?;
|
.await?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let is_conduwuit_admin = services.admin.user_is_admin(lowercased_user_id).await;
|
// Only sync admin status if LDAP can actually determine it.
|
||||||
|
// None means LDAP cannot determine admin status (manual config required).
|
||||||
|
if let Some(is_ldap_admin) = is_ldap_admin {
|
||||||
|
let is_conduwuit_admin = services.admin.user_is_admin(lowercased_user_id).await;
|
||||||
|
|
||||||
if is_ldap_admin && !is_conduwuit_admin {
|
if is_ldap_admin && !is_conduwuit_admin {
|
||||||
Box::pin(services.admin.make_user_admin(lowercased_user_id)).await?;
|
Box::pin(services.admin.make_user_admin(lowercased_user_id)).await?;
|
||||||
} else if !is_ldap_admin && is_conduwuit_admin {
|
} else if !is_ldap_admin && is_conduwuit_admin {
|
||||||
Box::pin(services.admin.revoke_admin(lowercased_user_id)).await?;
|
Box::pin(services.admin.revoke_admin(lowercased_user_id)).await?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(user_id)
|
Ok(user_id)
|
||||||
|
|||||||
@@ -1269,12 +1269,12 @@ impl Service {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "ldap"))]
|
#[cfg(not(feature = "ldap"))]
|
||||||
pub async fn search_ldap(&self, _user_id: &UserId) -> Result<Vec<(String, bool)>> {
|
pub async fn search_ldap(&self, _user_id: &UserId) -> Result<Vec<(String, Option<bool>)>> {
|
||||||
Err!(FeatureDisabled("ldap"))
|
Err!(FeatureDisabled("ldap"))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "ldap")]
|
#[cfg(feature = "ldap")]
|
||||||
pub async fn search_ldap(&self, user_id: &UserId) -> Result<Vec<(String, bool)>> {
|
pub async fn search_ldap(&self, user_id: &UserId) -> Result<Vec<(String, Option<bool>)>> {
|
||||||
let localpart = user_id.localpart().to_owned();
|
let localpart = user_id.localpart().to_owned();
|
||||||
let lowercased_localpart = localpart.to_lowercase();
|
let lowercased_localpart = localpart.to_lowercase();
|
||||||
|
|
||||||
@@ -1318,7 +1318,7 @@ impl Service {
|
|||||||
.inspect(|(entries, result)| trace!(?entries, ?result, "LDAP Search"))
|
.inspect(|(entries, result)| trace!(?entries, ?result, "LDAP Search"))
|
||||||
.map_err(|e| err!(Ldap(error!(?attr, ?user_filter, "LDAP search error: {e}"))))?;
|
.map_err(|e| err!(Ldap(error!(?attr, ?user_filter, "LDAP search error: {e}"))))?;
|
||||||
|
|
||||||
let mut dns: HashMap<String, bool> = entries
|
let mut dns: HashMap<String, Option<bool>> = entries
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter_map(|entry| {
|
.filter_map(|entry| {
|
||||||
let search_entry = SearchEntry::construct(entry);
|
let search_entry = SearchEntry::construct(entry);
|
||||||
@@ -1329,11 +1329,16 @@ impl Service {
|
|||||||
.into_iter()
|
.into_iter()
|
||||||
.chain(search_entry.attrs.get(&config.name_attribute))
|
.chain(search_entry.attrs.get(&config.name_attribute))
|
||||||
.any(|ids| ids.contains(&localpart) || ids.contains(&lowercased_localpart))
|
.any(|ids| ids.contains(&localpart) || ids.contains(&lowercased_localpart))
|
||||||
.then_some((search_entry.dn, false))
|
.then_some((search_entry.dn, None))
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
if !config.admin_filter.is_empty() {
|
if !config.admin_filter.is_empty() {
|
||||||
|
// Update all existing entries to Some(false) since we can now determine admin
|
||||||
|
// status
|
||||||
|
for admin_status in dns.values_mut() {
|
||||||
|
*admin_status = Some(false);
|
||||||
|
}
|
||||||
let admin_base_dn = if config.admin_base_dn.is_empty() {
|
let admin_base_dn = if config.admin_base_dn.is_empty() {
|
||||||
&config.base_dn
|
&config.base_dn
|
||||||
} else {
|
} else {
|
||||||
@@ -1362,7 +1367,7 @@ impl Service {
|
|||||||
.into_iter()
|
.into_iter()
|
||||||
.chain(search_entry.attrs.get(&config.name_attribute))
|
.chain(search_entry.attrs.get(&config.name_attribute))
|
||||||
.any(|ids| ids.contains(&localpart) || ids.contains(&lowercased_localpart))
|
.any(|ids| ids.contains(&localpart) || ids.contains(&lowercased_localpart))
|
||||||
.then_some((search_entry.dn, true))
|
.then_some((search_entry.dn, Some(true)))
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user