update
This commit is contained in:
parent
b4a832ae69
commit
248403b094
|
|
@ -1,15 +1,31 @@
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from functools import wraps
|
||||||
from typing import Dict, Optional
|
from typing import Dict, Optional
|
||||||
|
|
||||||
from ldap3 import ALL, BASE, Connection, MODIFY_REPLACE, Server
|
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 ldap3.utils.conv import escape_filter_chars
|
||||||
|
|
||||||
from ad_user_creator.exceptions import LdapConnectionError, LdapOperationError
|
from ad_user_creator.exceptions import LdapConnectionError, LdapOperationError
|
||||||
from ad_user_creator.models import LdapConfig
|
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:
|
class LdapClient:
|
||||||
def __init__(self, config: LdapConfig) -> None:
|
def __init__(self, config: LdapConfig) -> None:
|
||||||
self.config = config
|
self.config = config
|
||||||
|
|
@ -36,6 +52,7 @@ class LdapClient:
|
||||||
if self.conn is not None and self.conn.bound:
|
if self.conn is not None and self.conn.bound:
|
||||||
self.conn.unbind()
|
self.conn.unbind()
|
||||||
|
|
||||||
|
@_with_auto_reconnect
|
||||||
def user_exists(self, sam_account_name: str) -> bool:
|
def user_exists(self, sam_account_name: str) -> bool:
|
||||||
self.ensure_connected()
|
self.ensure_connected()
|
||||||
assert self.conn is not None
|
assert self.conn is not None
|
||||||
|
|
@ -46,6 +63,7 @@ class LdapClient:
|
||||||
return False
|
return False
|
||||||
return len(self.conn.entries) > 0
|
return len(self.conn.entries) > 0
|
||||||
|
|
||||||
|
@_with_auto_reconnect
|
||||||
def find_user_dn_by_sam(self, sam_account_name: str) -> Optional[str]:
|
def find_user_dn_by_sam(self, sam_account_name: str) -> Optional[str]:
|
||||||
self.ensure_connected()
|
self.ensure_connected()
|
||||||
assert self.conn is not None
|
assert self.conn is not None
|
||||||
|
|
@ -56,6 +74,7 @@ class LdapClient:
|
||||||
return None
|
return None
|
||||||
return str(self.conn.entries[0].distinguishedName.value)
|
return str(self.conn.entries[0].distinguishedName.value)
|
||||||
|
|
||||||
|
@_with_auto_reconnect
|
||||||
def group_exists(self, group_name: str) -> bool:
|
def group_exists(self, group_name: str) -> bool:
|
||||||
self.ensure_connected()
|
self.ensure_connected()
|
||||||
assert self.conn is not None
|
assert self.conn is not None
|
||||||
|
|
@ -66,6 +85,7 @@ class LdapClient:
|
||||||
return False
|
return False
|
||||||
return len(self.conn.entries) > 0
|
return len(self.conn.entries) > 0
|
||||||
|
|
||||||
|
@_with_auto_reconnect
|
||||||
def get_group_dn(self, group_name: str) -> str:
|
def get_group_dn(self, group_name: str) -> str:
|
||||||
self.ensure_connected()
|
self.ensure_connected()
|
||||||
assert self.conn is not None
|
assert self.conn is not None
|
||||||
|
|
@ -76,6 +96,7 @@ class LdapClient:
|
||||||
raise LdapOperationError(f"组不存在: {group_name}")
|
raise LdapOperationError(f"组不存在: {group_name}")
|
||||||
return str(self.conn.entries[0].distinguishedName.value)
|
return str(self.conn.entries[0].distinguishedName.value)
|
||||||
|
|
||||||
|
@_with_auto_reconnect
|
||||||
def get_group_gid_number(self, group_name: str) -> Optional[int]:
|
def get_group_gid_number(self, group_name: str) -> Optional[int]:
|
||||||
self.ensure_connected()
|
self.ensure_connected()
|
||||||
assert self.conn is not None
|
assert self.conn is not None
|
||||||
|
|
@ -95,6 +116,7 @@ class LdapClient:
|
||||||
except (TypeError, ValueError):
|
except (TypeError, ValueError):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
@_with_auto_reconnect
|
||||||
def create_user(self, user_dn: str, attributes: Dict[str, object]) -> None:
|
def create_user(self, user_dn: str, attributes: Dict[str, object]) -> None:
|
||||||
self.ensure_connected()
|
self.ensure_connected()
|
||||||
assert self.conn is not None
|
assert self.conn is not None
|
||||||
|
|
@ -102,6 +124,7 @@ class LdapClient:
|
||||||
if not ok:
|
if not ok:
|
||||||
raise LdapOperationError(f"创建用户失败: {self.conn.result}")
|
raise LdapOperationError(f"创建用户失败: {self.conn.result}")
|
||||||
|
|
||||||
|
@_with_auto_reconnect
|
||||||
def set_user_password(self, user_dn: str, new_password: str) -> None:
|
def set_user_password(self, user_dn: str, new_password: str) -> None:
|
||||||
self.ensure_connected()
|
self.ensure_connected()
|
||||||
assert self.conn is not None
|
assert self.conn is not None
|
||||||
|
|
@ -109,6 +132,7 @@ class LdapClient:
|
||||||
if not ok:
|
if not ok:
|
||||||
raise LdapOperationError(f"设置用户密码失败 user={user_dn} result={self.conn.result}")
|
raise LdapOperationError(f"设置用户密码失败 user={user_dn} result={self.conn.result}")
|
||||||
|
|
||||||
|
@_with_auto_reconnect
|
||||||
def set_user_enabled(self, user_dn: str, enabled: bool) -> None:
|
def set_user_enabled(self, user_dn: str, enabled: bool) -> None:
|
||||||
self.ensure_connected()
|
self.ensure_connected()
|
||||||
assert self.conn is not None
|
assert self.conn is not None
|
||||||
|
|
@ -118,6 +142,7 @@ class LdapClient:
|
||||||
action = "启用" if enabled else "禁用"
|
action = "启用" if enabled else "禁用"
|
||||||
raise LdapOperationError(f"{action}用户失败 user={user_dn} result={self.conn.result}")
|
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:
|
def add_user_to_group(self, user_dn: str, group_dn: str) -> None:
|
||||||
self.ensure_connected()
|
self.ensure_connected()
|
||||||
assert self.conn is not None
|
assert self.conn is not None
|
||||||
|
|
@ -127,6 +152,7 @@ class LdapClient:
|
||||||
f"添加组成员失败 user={user_dn} group={group_dn} result={self.conn.result}"
|
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]:
|
def get_user_attributes(self, user_dn: str, attrs: list[str]) -> Dict[str, str]:
|
||||||
self.ensure_connected()
|
self.ensure_connected()
|
||||||
assert self.conn is not None
|
assert self.conn is not None
|
||||||
|
|
@ -148,6 +174,7 @@ class LdapClient:
|
||||||
result[attr] = ""
|
result[attr] = ""
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
@_with_auto_reconnect
|
||||||
def modify_user_attributes(self, user_dn: str, changes: Dict[str, str]) -> None:
|
def modify_user_attributes(self, user_dn: str, changes: Dict[str, str]) -> None:
|
||||||
self.ensure_connected()
|
self.ensure_connected()
|
||||||
assert self.conn is not None
|
assert self.conn is not None
|
||||||
|
|
@ -156,6 +183,7 @@ class LdapClient:
|
||||||
if not ok:
|
if not ok:
|
||||||
raise LdapOperationError(f"更新用户属性失败 user={user_dn} result={self.conn.result}")
|
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:
|
def add_user_to_group_if_missing(self, user_dn: str, group_dn: str) -> bool:
|
||||||
self.ensure_connected()
|
self.ensure_connected()
|
||||||
assert self.conn is not None
|
assert self.conn is not None
|
||||||
|
|
|
||||||
|
|
@ -301,3 +301,4 @@
|
||||||
2026-03-17 10:44:31,846 [INFO] 配置加载完成
|
2026-03-17 10:44:31,846 [INFO] 配置加载完成
|
||||||
2026-03-19 23:46:47,952 [INFO] 配置加载完成
|
2026-03-19 23:46:47,952 [INFO] 配置加载完成
|
||||||
2026-03-24 12:16:13,498 [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,
|
"next_uid_number": 2133,
|
||||||
"updated_at": "2026-03-17T02:44:35+00:00"
|
"updated_at": "2026-03-24T09:58:17+00:00"
|
||||||
}
|
}
|
||||||
Loading…
Reference in New Issue