update
This commit is contained in:
parent
b4a832ae69
commit
248403b094
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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] 配置加载完成
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
}
|
||||
Loading…
Reference in New Issue