update
This commit is contained in:
parent
ea5e6cca0e
commit
d12cc71bd4
|
|
@ -173,6 +173,50 @@ def _proxy_addresses(email: str, sam: str, alias_domain: str | None) -> list[str
|
|||
return out
|
||||
|
||||
|
||||
def _target_values(value: Any) -> list[str]:
|
||||
if isinstance(value, (list, tuple, set)):
|
||||
return [str(x).strip() for x in value if x is not None and str(x).strip() != ""]
|
||||
if value is None or str(value).strip() == "":
|
||||
return []
|
||||
return [str(value).strip()]
|
||||
|
||||
|
||||
def _ad_values(attrs: dict[str, Any], attr_name: str) -> list[str]:
|
||||
raw = attrs.get(attr_name)
|
||||
if raw is None:
|
||||
lower_attr = attr_name.lower()
|
||||
for key, value in attrs.items():
|
||||
if str(key).lower() == lower_attr:
|
||||
raw = value
|
||||
break
|
||||
if isinstance(raw, (list, tuple, set)):
|
||||
return [str(x).strip() for x in raw if x is not None and str(x).strip() != ""]
|
||||
if raw is None or str(raw).strip() == "":
|
||||
return []
|
||||
return [str(raw).strip()]
|
||||
|
||||
|
||||
def _canonical_values(attr_name: str, values: list[str]) -> list[str]:
|
||||
if attr_name in {"proxyAddresses"}:
|
||||
return sorted(values)
|
||||
if attr_name in {"manager", "mail", "sAMAccountName"}:
|
||||
return sorted([v.lower() for v in values])
|
||||
return sorted(values)
|
||||
|
||||
|
||||
def _diff_ad_attributes(ad_attrs: dict[str, Any], target_attrs: dict[str, Any]) -> dict[str, Any]:
|
||||
diff: dict[str, Any] = {}
|
||||
for attr_name, target_value in target_attrs.items():
|
||||
wanted = _target_values(target_value)
|
||||
if not wanted:
|
||||
continue
|
||||
current = _ad_values(ad_attrs, attr_name)
|
||||
if _canonical_values(attr_name, current) == _canonical_values(attr_name, wanted):
|
||||
continue
|
||||
diff[attr_name] = target_value
|
||||
return diff
|
||||
|
||||
|
||||
def _location_from_workplace(workplace: str, mappings: dict[str, Any] | None = None) -> dict[str, Any]:
|
||||
text = str(workplace or "").strip()
|
||||
defaults: dict[str, dict[str, Any]] = {
|
||||
|
|
@ -409,10 +453,36 @@ class SyncEhrToAdUserJob(BaseJob):
|
|||
|
||||
processed = 0
|
||||
updated = 0
|
||||
skipped_unchanged = 0
|
||||
skipped_missing_sam = 0
|
||||
skipped_not_found_ad = 0
|
||||
failed = 0
|
||||
manager_dn_cache: dict[str, str] = {}
|
||||
ad_compare_attributes = [
|
||||
"sAMAccountName",
|
||||
"givenName",
|
||||
"sn",
|
||||
"title",
|
||||
"department",
|
||||
"manager",
|
||||
"proxyAddresses",
|
||||
"co",
|
||||
"c",
|
||||
"countryCode",
|
||||
"company",
|
||||
"displayName",
|
||||
"mail",
|
||||
"employeeID",
|
||||
"employeeType",
|
||||
"mobile",
|
||||
"physicalDeliveryOfficeName",
|
||||
"postalCode",
|
||||
"st",
|
||||
"l",
|
||||
"streetAddress",
|
||||
]
|
||||
if department_code_attr:
|
||||
ad_compare_attributes.append(department_code_attr)
|
||||
|
||||
for sam_key, item in users_by_sam.items():
|
||||
emp = item.get("employeeInfo") or {}
|
||||
|
|
@ -429,7 +499,7 @@ class SyncEhrToAdUserJob(BaseJob):
|
|||
processed += 1
|
||||
|
||||
try:
|
||||
ad_user = ad.find_user(sam)
|
||||
ad_user = ad.find_user(sam, attributes=ad_compare_attributes)
|
||||
if not ad_user:
|
||||
skipped_not_found_ad += 1
|
||||
logger.warning("AD 用户不存在,跳过:sAMAccountName=%s", sam)
|
||||
|
|
@ -493,15 +563,22 @@ class SyncEhrToAdUserJob(BaseJob):
|
|||
if department_code_attr and department_code:
|
||||
attributes[department_code_attr] = department_code
|
||||
|
||||
changed = ad.modify_user(str(ad_user["dn"]), attributes, dry_run=dry_run)
|
||||
diff_attributes = _diff_ad_attributes(ad_user.get("attributes") or {}, attributes)
|
||||
if not diff_attributes:
|
||||
skipped_unchanged += 1
|
||||
if verbose_trace:
|
||||
logger.info("AD 用户信息一致,跳过更新:sam=%s dn=%s", sam, ad_user["dn"])
|
||||
continue
|
||||
|
||||
changed = ad.modify_user(str(ad_user["dn"]), diff_attributes, dry_run=dry_run)
|
||||
if changed:
|
||||
updated += 1
|
||||
if verbose_trace:
|
||||
logger.info(
|
||||
"AD 用户同步完成:sam=%s dn=%s attrs=%s",
|
||||
"AD 用户同步完成:sam=%s dn=%s changed_attrs=%s",
|
||||
sam,
|
||||
ad_user["dn"],
|
||||
json.dumps({k: v for k, v in attributes.items() if v}, ensure_ascii=False, default=str),
|
||||
json.dumps({k: v for k, v in diff_attributes.items() if v}, ensure_ascii=False, default=str),
|
||||
)
|
||||
except Exception as e: # noqa: BLE001
|
||||
failed += 1
|
||||
|
|
@ -514,6 +591,7 @@ class SyncEhrToAdUserJob(BaseJob):
|
|||
"ehr_current_users_with_ad_account": len(users_by_sam),
|
||||
"processed": processed,
|
||||
"updated": updated,
|
||||
"skipped_unchanged": skipped_unchanged,
|
||||
"skipped_missing_sam": skipped_missing_sam,
|
||||
"skipped_not_found_ad": skipped_not_found_ad,
|
||||
"failed": failed,
|
||||
|
|
|
|||
Loading…
Reference in New Issue