fix: [FL-195][创建用户报错] 为用户服务事务添加异常处理和回滚机制
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Co-authored-by: multica-agent <github@multica.ai>
This commit is contained in:
@@ -114,20 +114,24 @@ def create_user(
|
|||||||
status="ENABLED",
|
status="ENABLED",
|
||||||
)
|
)
|
||||||
|
|
||||||
db.add(user)
|
try:
|
||||||
db.flush()
|
db.add(user)
|
||||||
_assign_legacy_roles(db, user_id, [])
|
db.flush()
|
||||||
write_audit_log(
|
_assign_legacy_roles(db, user_id, [])
|
||||||
db,
|
write_audit_log(
|
||||||
action="user.create",
|
db,
|
||||||
actor_user_id=actor_user_id,
|
action="user.create",
|
||||||
detail=compose_audit_detail(
|
actor_user_id=actor_user_id,
|
||||||
f"target_user_id={user.id}",
|
detail=compose_audit_detail(
|
||||||
f"target_username={user.username}",
|
f"target_user_id={user.id}",
|
||||||
f"target_status={user.status}",
|
f"target_username={user.username}",
|
||||||
),
|
f"target_status={user.status}",
|
||||||
)
|
),
|
||||||
db.commit()
|
)
|
||||||
|
db.commit()
|
||||||
|
except SQLAlchemyError:
|
||||||
|
db.rollback()
|
||||||
|
return None
|
||||||
|
|
||||||
created = get_user_by_id(db, user_id)
|
created = get_user_by_id(db, user_id)
|
||||||
if created:
|
if created:
|
||||||
@@ -150,18 +154,22 @@ def delete_user(db: Session, user_id: str, *, actor_user_id: str | None) -> bool
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
target_username = user.username
|
target_username = user.username
|
||||||
revoke_active_sessions_for_user(db, user_id)
|
try:
|
||||||
write_audit_log(
|
revoke_active_sessions_for_user(db, user_id)
|
||||||
db,
|
write_audit_log(
|
||||||
action="user.delete",
|
db,
|
||||||
actor_user_id=actor_user_id,
|
action="user.delete",
|
||||||
detail=compose_audit_detail(
|
actor_user_id=actor_user_id,
|
||||||
f"target_user_id={user_id}",
|
detail=compose_audit_detail(
|
||||||
f"target_username={target_username}",
|
f"target_user_id={user_id}",
|
||||||
),
|
f"target_username={target_username}",
|
||||||
)
|
),
|
||||||
db.delete(user)
|
)
|
||||||
db.commit()
|
db.delete(user)
|
||||||
|
db.commit()
|
||||||
|
except SQLAlchemyError:
|
||||||
|
db.rollback()
|
||||||
|
return False
|
||||||
|
|
||||||
_fire_and_forget(
|
_fire_and_forget(
|
||||||
publish_topic(
|
publish_topic(
|
||||||
@@ -186,20 +194,24 @@ def reset_user_password(
|
|||||||
if not user:
|
if not user:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
user.password_hash = hash_password(payload.new_password)
|
try:
|
||||||
revoke_active_sessions_for_user(db, user_id)
|
user.password_hash = hash_password(payload.new_password)
|
||||||
write_audit_log(
|
revoke_active_sessions_for_user(db, user_id)
|
||||||
db,
|
write_audit_log(
|
||||||
action="user.password.reset",
|
db,
|
||||||
actor_user_id=actor_user_id,
|
action="user.password.reset",
|
||||||
detail=compose_audit_detail(
|
actor_user_id=actor_user_id,
|
||||||
f"target_user_id={user.id}",
|
detail=compose_audit_detail(
|
||||||
f"target_username={user.username}",
|
f"target_user_id={user.id}",
|
||||||
"password_updated=true",
|
f"target_username={user.username}",
|
||||||
"sessions_revoked=true",
|
"password_updated=true",
|
||||||
),
|
"sessions_revoked=true",
|
||||||
)
|
),
|
||||||
db.commit()
|
)
|
||||||
|
db.commit()
|
||||||
|
except SQLAlchemyError:
|
||||||
|
db.rollback()
|
||||||
|
return None
|
||||||
|
|
||||||
updated = get_user_by_id(db, user_id)
|
updated = get_user_by_id(db, user_id)
|
||||||
if updated:
|
if updated:
|
||||||
@@ -276,22 +288,27 @@ def update_user(
|
|||||||
if not changed_fields:
|
if not changed_fields:
|
||||||
return serialize_user(user)
|
return serialize_user(user)
|
||||||
|
|
||||||
write_audit_log(
|
try:
|
||||||
db,
|
write_audit_log(
|
||||||
action="user.update",
|
db,
|
||||||
actor_user_id=actor_user_id,
|
action="user.update",
|
||||||
detail=compose_audit_detail(
|
actor_user_id=actor_user_id,
|
||||||
f"target_user_id={user.id}",
|
detail=compose_audit_detail(
|
||||||
f"target_username={user.username}",
|
f"target_user_id={user.id}",
|
||||||
describe_changed_fields(changed_fields),
|
f"target_username={user.username}",
|
||||||
(
|
describe_changed_fields(changed_fields),
|
||||||
f"status_transition={previous_status}->{user.status}"
|
(
|
||||||
if status_changed
|
f"status_transition={previous_status}->{user.status}"
|
||||||
else None
|
if status_changed
|
||||||
|
else None
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
)
|
||||||
)
|
db.commit()
|
||||||
db.commit()
|
except SQLAlchemyError:
|
||||||
|
db.rollback()
|
||||||
|
return None
|
||||||
|
|
||||||
updated = get_user_by_id(db, user_id)
|
updated = get_user_by_id(db, user_id)
|
||||||
if updated:
|
if updated:
|
||||||
queue_user_auth_refresh(updated, status_changed=status_changed)
|
queue_user_auth_refresh(updated, status_changed=status_changed)
|
||||||
@@ -339,17 +356,21 @@ def set_user_roles(
|
|||||||
updated = get_user_by_id(db, user_id)
|
updated = get_user_by_id(db, user_id)
|
||||||
if updated:
|
if updated:
|
||||||
authz = get_user_authorization(db, updated.id)
|
authz = get_user_authorization(db, updated.id)
|
||||||
write_audit_log(
|
try:
|
||||||
db,
|
write_audit_log(
|
||||||
action="user.roles.replace",
|
db,
|
||||||
actor_user_id=actor_user_id,
|
action="user.roles.replace",
|
||||||
detail=compose_audit_detail(
|
actor_user_id=actor_user_id,
|
||||||
f"target_user_id={updated.id}",
|
detail=compose_audit_detail(
|
||||||
f"target_username={updated.username}",
|
f"target_user_id={updated.id}",
|
||||||
f"role_codes={summarize_values(sorted(authz.role_codes))}",
|
f"target_username={updated.username}",
|
||||||
),
|
f"role_codes={summarize_values(sorted(authz.role_codes))}",
|
||||||
)
|
),
|
||||||
db.commit()
|
)
|
||||||
|
db.commit()
|
||||||
|
except SQLAlchemyError:
|
||||||
|
db.rollback()
|
||||||
|
return None
|
||||||
queue_user_auth_refresh(updated)
|
queue_user_auth_refresh(updated)
|
||||||
_fire_and_forget(
|
_fire_and_forget(
|
||||||
publish_topic(
|
publish_topic(
|
||||||
|
|||||||
Reference in New Issue
Block a user