From 13395ea3e30628f3db93016d0b0e1407f43a1c35 Mon Sep 17 00:00:00 2001 From: NoahLan <6995syu@163.com> Date: Mon, 9 Feb 2026 03:59:25 +0800 Subject: [PATCH] fix: missing user_attributes (cherry picked from commit d7310c7fbd446dbf76e9373abf1dda276ad47307) --- .../routes/sys/schemas/user_attribute.py | 67 +++++++ iti/applications/routes/sys/user_attribute.py | 187 ++++++++++++++++++ 2 files changed, 254 insertions(+) create mode 100644 iti/applications/routes/sys/schemas/user_attribute.py create mode 100644 iti/applications/routes/sys/user_attribute.py diff --git a/iti/applications/routes/sys/schemas/user_attribute.py b/iti/applications/routes/sys/schemas/user_attribute.py new file mode 100644 index 0000000..5b2fece --- /dev/null +++ b/iti/applications/routes/sys/schemas/user_attribute.py @@ -0,0 +1,67 @@ +""" +用户扩展属性 API Schema +""" +from marshmallow import Schema, fields, validate + + +class UserAttributeQuery(Schema): + """查询用户扩展属性请求""" + + group = fields.String( + required=False, metadata={"description": "属性分组(可选,不传则返回所有分组)"} + ) + + +class UserAttributeSetRequest(Schema): + """设置用户扩展属性请求""" + + attributes = fields.Dict( + required=True, + metadata={ + "description": "属性字典,格式:{'key1': 'value1', 'key2': 'value2'} 或 {'group1': {'key1': 'value1'}, 'group2': {...}}" + }, + ) + group = fields.String( + required=False, + metadata={"description": "属性分组(可选,指定后 attributes 为简单键值对)"}, + ) + + +class UserAttributeItemRequest(Schema): + """单个属性设置请求""" + + attr_value = fields.String(required=True, metadata={"description": "属性值"}) + attr_type = fields.String( + required=False, + load_default="string", + validate=validate.OneOf(["string", "int", "float", "bool", "json", "encrypted"]), + metadata={"description": "属性类型"}, + ) + + +class UserAttributeBatchRequest(Schema): + """批量设置属性请求(支持类型)""" + + class AttributeItem(Schema): + attr_group = fields.String(required=True, metadata={"description": "属性分组"}) + attr_key = fields.String(required=True, metadata={"description": "属性键"}) + attr_value = fields.String(required=True, metadata={"description": "属性值"}) + attr_type = fields.String( + required=False, + load_default="string", + validate=validate.OneOf( + ["string", "int", "float", "bool", "json", "encrypted"] + ), + metadata={"description": "属性类型"}, + ) + description = fields.String( + required=False, metadata={"description": "属性描述"} + ) + sort = fields.Integer(required=False, load_default=0, metadata={"description": "排序"}) + + attributes = fields.List( + fields.Nested(AttributeItem), + required=True, + metadata={"description": "属性列表"}, + ) + diff --git a/iti/applications/routes/sys/user_attribute.py b/iti/applications/routes/sys/user_attribute.py new file mode 100644 index 0000000..a728148 --- /dev/null +++ b/iti/applications/routes/sys/user_attribute.py @@ -0,0 +1,187 @@ +""" +用户扩展属性 API 路由 +""" +from apiflask import APIBlueprint +from flask_jwt_extended import jwt_required, current_user +from iti.applications.common.utils import success +from iti.applications.extensions import sys_log, db +from iti.applications.common.enums import LogType +from iti.applications.common.exceptions.biz_exp import BizException +from iti.applications.service.sys import sys_user_attribute as attr_service +from .schemas.user_attribute import ( + UserAttributeQuery, + UserAttributeSetRequest, + UserAttributeItemRequest, + UserAttributeBatchRequest, +) +from marshmallow import Schema, fields + +bp = APIBlueprint( + "sys_user_attribute", + __name__, + url_prefix="/user/attributes", + tag="系统.用户扩展属性", +) + + +@bp.get("/") +@jwt_required() +@bp.doc(security="JWT") +@bp.input(UserAttributeQuery, location="query") +@bp.output(Schema.from_dict({"attributes": fields.Dict()})) +def get_user_attributes(user_id: str, query_data: dict): + """ + 获取用户扩展属性 + """ + group = query_data.get("group") + attributes = attr_service.get_user_attributes(user_id, group) + return success({"attributes": attributes}) + + +@bp.put("/") +@jwt_required() +@bp.doc(security="JWT") +@bp.input(UserAttributeSetRequest, location="json") +@sys_log( + name="设置用户扩展属性", + desc="批量设置用户扩展属性", + type=LogType.OPERATION, + save_db=True, + execute_time=True, +) +def set_user_attributes(user_id: str, json_data: dict): + """ + 批量设置用户扩展属性 + """ + attributes = json_data.get("attributes") + group = json_data.get("group") + + attr_service.set_user_attributes(user_id, attributes, group) + return success(message="设置成功") + + +@bp.delete("//") +@jwt_required() +@bp.doc(security="JWT") +@sys_log( + name="删除用户扩展属性", + desc="删除用户扩展属性分组或单个属性", + type=LogType.OPERATION, + save_db=True, + execute_time=True, +) +def delete_user_attributes(user_id: str, group: str): + """ + 删除用户扩展属性(整个分组) + """ + attr_service.delete_user_attribute(user_id, group) + return success(message="删除成功") + + +@bp.delete("///") +@jwt_required() +@bp.doc(security="JWT") +@sys_log( + name="删除用户扩展属性", + desc="删除用户单个扩展属性", + type=LogType.OPERATION, + save_db=True, + execute_time=True, +) +def delete_user_attribute_key(user_id: str, group: str, key: str): + """ + 删除用户单个扩展属性 + """ + attr_service.delete_user_attribute(user_id, group, key) + return success(message="删除成功") + + +@bp.get("///") +@jwt_required() +@bp.doc(security="JWT") +@bp.output(Schema.from_dict({"value": fields.Raw()})) +def get_user_attribute_value(user_id: str, group: str, key: str): + """ + 获取单个属性值 + """ + value = attr_service.get_user_attribute_value(user_id, group, key) + return success({"value": value}) + + +@bp.put("///") +@jwt_required() +@bp.doc(security="JWT") +@bp.input(UserAttributeItemRequest, location="json") +@sys_log( + name="设置用户扩展属性", + desc="设置用户单个扩展属性", + type=LogType.OPERATION, + save_db=True, + execute_time=True, +) +def set_user_attribute_value(user_id: str, group: str, key: str, json_data: dict): + """ + 设置单个属性值 + """ + value = json_data.get("attr_value") + attr_type = json_data.get("attr_type", "string") + + attr_service.set_user_attribute_value(user_id, group, key, value, attr_type) + return success(message="设置成功") + + +@bp.post("//batch") +@jwt_required() +@bp.doc(security="JWT") +@bp.input(UserAttributeBatchRequest, location="json") +@sys_log( + name="批量设置用户扩展属性", + desc="批量设置用户扩展属性(支持类型)", + type=LogType.OPERATION, + save_db=True, + execute_time=True, +) +def batch_set_user_attributes(user_id: str, json_data: dict): + """ + 批量设置用户扩展属性(支持指定类型、描述、排序) + """ + attributes = json_data.get("attributes", []) + attr_service.batch_set_user_attributes_with_type(user_id, attributes) + return success(message="批量设置成功") + + +@bp.get("/current") +@jwt_required() +@bp.doc(security="JWT") +@bp.input(UserAttributeQuery, location="query") +@bp.output(Schema.from_dict({"attributes": fields.Dict()})) +def get_current_user_attributes(query_data: dict): + """ + 获取当前用户的扩展属性 + """ + group = query_data.get("group") + attributes = attr_service.get_user_attributes(current_user.id, group) + return success({"attributes": attributes}) + + +@bp.put("/current") +@jwt_required() +@bp.doc(security="JWT") +@bp.input(UserAttributeSetRequest, location="json") +@sys_log( + name="设置当前用户扩展属性", + desc="设置当前用户扩展属性", + type=LogType.OPERATION, + save_db=True, + execute_time=True, +) +def set_current_user_attributes(json_data: dict): + """ + 设置当前用户的扩展属性 + """ + attributes = json_data.get("attributes") + group = json_data.get("group") + + attr_service.set_user_attributes(current_user.id, attributes, group) + return success(message="设置成功") +