This commit is contained in:
Marsway 2026-03-24 18:07:31 +08:00
parent b4a832ae69
commit 248403b094
4 changed files with 32 additions and 3 deletions

View File

@ -1,15 +1,31 @@
from __future__ import annotations
from functools import wraps
from typing import Dict, Optional
from ldap3 import ALL, BASE, Connection, MODIFY_REPLACE, Server
from ldap3.core.exceptions import LDAPException
from ldap3.core.exceptions import LDAPException, LDAPCommunicationError
from ldap3.utils.conv import escape_filter_chars
from ad_user_creator.exceptions import LdapConnectionError, LdapOperationError
from ad_user_creator.models import LdapConfig
def _with_auto_reconnect(func):
"""
捕获底层 LDAP 网络异常并自动重连重试一次
适用于使用长连接时防止因网络波动或闲置导致的 EOF 错误
"""
@wraps(func)
def wrapper(self: "LdapClient", *args, **kwargs):
try:
return func(self, *args, **kwargs)
except LDAPCommunicationError:
self.connect()
return func(self, *args, **kwargs)
return wrapper
class LdapClient:
def __init__(self, config: LdapConfig) -> None:
self.config = config
@ -36,6 +52,7 @@ class LdapClient:
if self.conn is not None and self.conn.bound:
self.conn.unbind()
@_with_auto_reconnect
def user_exists(self, sam_account_name: str) -> bool:
self.ensure_connected()
assert self.conn is not None
@ -46,6 +63,7 @@ class LdapClient:
return False
return len(self.conn.entries) > 0
@_with_auto_reconnect
def find_user_dn_by_sam(self, sam_account_name: str) -> Optional[str]:
self.ensure_connected()
assert self.conn is not None
@ -56,6 +74,7 @@ class LdapClient:
return None
return str(self.conn.entries[0].distinguishedName.value)
@_with_auto_reconnect
def group_exists(self, group_name: str) -> bool:
self.ensure_connected()
assert self.conn is not None
@ -66,6 +85,7 @@ class LdapClient:
return False
return len(self.conn.entries) > 0
@_with_auto_reconnect
def get_group_dn(self, group_name: str) -> str:
self.ensure_connected()
assert self.conn is not None
@ -76,6 +96,7 @@ class LdapClient:
raise LdapOperationError(f"组不存在: {group_name}")
return str(self.conn.entries[0].distinguishedName.value)
@_with_auto_reconnect
def get_group_gid_number(self, group_name: str) -> Optional[int]:
self.ensure_connected()
assert self.conn is not None
@ -95,6 +116,7 @@ class LdapClient:
except (TypeError, ValueError):
return None
@_with_auto_reconnect
def create_user(self, user_dn: str, attributes: Dict[str, object]) -> None:
self.ensure_connected()
assert self.conn is not None
@ -102,6 +124,7 @@ class LdapClient:
if not ok:
raise LdapOperationError(f"创建用户失败: {self.conn.result}")
@_with_auto_reconnect
def set_user_password(self, user_dn: str, new_password: str) -> None:
self.ensure_connected()
assert self.conn is not None
@ -109,6 +132,7 @@ class LdapClient:
if not ok:
raise LdapOperationError(f"设置用户密码失败 user={user_dn} result={self.conn.result}")
@_with_auto_reconnect
def set_user_enabled(self, user_dn: str, enabled: bool) -> None:
self.ensure_connected()
assert self.conn is not None
@ -118,6 +142,7 @@ class LdapClient:
action = "启用" if enabled else "禁用"
raise LdapOperationError(f"{action}用户失败 user={user_dn} result={self.conn.result}")
@_with_auto_reconnect
def add_user_to_group(self, user_dn: str, group_dn: str) -> None:
self.ensure_connected()
assert self.conn is not None
@ -127,6 +152,7 @@ class LdapClient:
f"添加组成员失败 user={user_dn} group={group_dn} result={self.conn.result}"
)
@_with_auto_reconnect
def get_user_attributes(self, user_dn: str, attrs: list[str]) -> Dict[str, str]:
self.ensure_connected()
assert self.conn is not None
@ -148,6 +174,7 @@ class LdapClient:
result[attr] = ""
return result
@_with_auto_reconnect
def modify_user_attributes(self, user_dn: str, changes: Dict[str, str]) -> None:
self.ensure_connected()
assert self.conn is not None
@ -156,6 +183,7 @@ class LdapClient:
if not ok:
raise LdapOperationError(f"更新用户属性失败 user={user_dn} result={self.conn.result}")
@_with_auto_reconnect
def add_user_to_group_if_missing(self, user_dn: str, group_dn: str) -> bool:
self.ensure_connected()
assert self.conn is not None

View File

@ -301,3 +301,4 @@
2026-03-17 10:44:31,846 [INFO] 配置加载完成
2026-03-19 23:46:47,952 [INFO] 配置加载完成
2026-03-24 12:16:13,498 [INFO] 配置加载完成
2026-03-24 17:57:59,426 [INFO] 配置加载完成

View File

@ -1,4 +1,4 @@
{
"next_uid_number": 2132,
"updated_at": "2026-03-17T02:44:35+00:00"
"next_uid_number": 2133,
"updated_at": "2026-03-24T09:58:17+00:00"
}

0
state/web.log Normal file
View File