libushang 3 months ago
parent
commit
1ac4a0e9e5

+ 1 - 1
common/TassApi.py

@@ -43,7 +43,7 @@ def HmacVerify(sign_data: str, sign_mac: str) -> str:
     response = requests.post(url=API_ROOT + "/HmacVerify", headers=headers, json=data, timeout=600)
     if response.status_code == 200:
         result = response.json()
-        print(result)
+        # print(result)
         if result['errcode'] == 0:
             return result['data'] == "success"
     return False

+ 72 - 0
common/enc/emergency_contact_info_data.py

@@ -0,0 +1,72 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+from . import mpfun
+from models import *
+from sqlalchemy.orm import Session
+from database import get_local_db
+
+# 应急预案人员信息表
+
+# 加密和HMAC签名
+def sign_row(db: Session, row: EmergencyContactInfo) -> None:
+    if row.sign != '':
+        return
+    
+    unit_id = str(row.unit_id) # 单位ID
+    unit_name = mpfun.base64_data(row.unit_name) # 单位名称
+    contact_name = mpfun.base64_data(row.contact_name) # 联系人
+    position = mpfun.base64_data(row.position) # 职务
+    yue_gov_ease_phone = mpfun.enc_data(row.yue_gov_ease_phone) # 粤政易手机号码
+    del_flag = row.del_flag # 是否已删除
+
+    sign_data = ",".join([unit_id, unit_name, contact_name, position, yue_gov_ease_phone, del_flag])
+    sign_hmac = mpfun.sign_data(sign_data)
+    # print('sign_tbl_user sign_data:', sign_data)
+    # print('sign_tbl_user sign_hmac:', sign_hmac)
+
+    row.yue_gov_ease_phone = yue_gov_ease_phone
+    row.sign = sign_hmac
+    
+    db.commit()
+
+# 比较字段合并字符串是否和MAC值匹配上,调用密码服务器[验证HMAC]接口
+def sign_valid_row(row: EmergencyContactInfo) -> bool:
+    if row.sign == '':
+        return True
+
+    # 关键字段合并字符串
+    sign_data = get_sign_str(row)
+    # print('sys_user sign_data:', sign_data)
+    
+    # 原HMACSM3数值
+    sign_hmac = row.sign
+    # print('sign_hmac:', sign_hmac)
+
+    return mpfun.hmac_verify(sign_data, sign_hmac)
+
+# 生成待签名的字符串
+def get_sign_str(row: EmergencyContactInfo) -> str:
+    unit_id = str(row.unit_id) # 单位ID
+    unit_name = mpfun.base64_data(row.unit_name) # 单位名称
+    contact_name = mpfun.base64_data(row.contact_name) # 联系人
+    position = mpfun.base64_data(row.position) # 职务
+    yue_gov_ease_phone = row.yue_gov_ease_phone # 粤政易手机号码
+    del_flag = row.del_flag # 是否已删除
+
+    # 关键字段合并字符串
+    sign_data = ",".join([unit_id, unit_name, contact_name, position, yue_gov_ease_phone, del_flag])
+    return sign_data
+
+# 生成HAMC签名值
+def get_sign_hmac(row: EmergencyContactInfo) -> str:
+    sign_data = get_sign_str(row)
+    return mpfun.sign_data(sign_data) 
+
+# 对所有数据进行签名
+def sign_table():
+    print('sign_emergency_contact_info table =====>>>')
+    with get_local_db() as db:
+        rows = db.query(EmergencyContactInfo).filter(EmergencyContactInfo.sign == '').all()
+        for row in rows:
+            sign_row(db, row)

+ 2 - 1
common/enc/mpfun.py

@@ -21,7 +21,8 @@ def sign_data(data: any)->str:
 
 # 对含有中文的数据进行BASE64处理
 def base64_data(val: str):
-    return str(base64.b64encode(val.encode("utf-8")), "utf-8")
+    data = val if val is not None else ''
+    return str(base64.b64encode(data.encode("utf-8")), "utf-8")
 
 # 比较字段合并字符串是否和MAC值匹配上,调用密码服务器[验证HMAC]接口
 def hmac_verify(sign_data: str, sign_hmac: str) -> bool:

+ 1 - 1
common/enc/sys_czrz_data.py

@@ -68,7 +68,7 @@ def get_sign_hmac(row: CzrzEntity) -> str:
 
 # 对所有数据进行签名
 def sign_table():
-    print('sign_tp_czrztp_czrz table =====>>>')
+    print('sign_tp_czrz table =====>>>')
     with get_local_db() as db:
         rows = db.query(CzrzEntity).filter(CzrzEntity.sign == '').all()
         for row in rows:

+ 80 - 0
common/enc/sys_menu_data.py

@@ -0,0 +1,80 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+from . import mpfun
+from models import *
+from utils import *
+from sqlalchemy.orm import Session
+from database import get_local_db
+
+# 菜单表
+
+# 加密和HMAC签名
+def sign_row(db: Session, row: SysMenu) -> None:
+    if row.sign != '':
+        return
+    
+    menu_id = str(row.menu_id) # 菜单ID
+    menu_name = mpfun.base64_data(row.menu_name) # 菜单名称
+    parent_id = str(row.parent_id) # 父菜单ID
+    order_num = str(row.order_num) # 显示顺序
+    path = mpfun.base64_data(row.path) # 路由地址
+    component = mpfun.base64_data(row.component) # 组件路径
+    menu_type = row.menu_type # 菜单类型
+    visible = row.visible # 显示状态
+    status = str(row.status) # 状态
+    del_flag = row.del_flag # 删除标志
+
+    sign_data = ",".join([menu_id, menu_name, parent_id, order_num, path, component, menu_type, visible, status, del_flag])
+    sign_hmac = mpfun.sign_data(sign_data)
+    # print('sign_tbl_post sign_data:', sign_data)
+    # print('sign_tbl_post sign_hmac:', sign_hmac)
+
+    row.sign = sign_hmac
+    
+    db.commit()
+    
+# 比较字段合并字符串是否和MAC值匹配上,调用密码服务器[验证HMAC]接口
+def sign_valid_row(row: SysMenu) -> bool:
+    if row.sign == '':
+        return True
+
+    # 关键字段合并字符串
+    sign_data = get_sign_str(row)
+    # print('sys_post sign_data:', sign_data)
+    
+    # 原HMACSM3数值
+    sign_hmac = row.sign
+    # print('sign_hmac:', sign_hmac)
+
+    return mpfun.hmac_verify(sign_data, sign_hmac)
+
+# 生成待签名的字符串
+def get_sign_str(row: SysMenu) -> str:
+    menu_id = str(row.menu_id) # 菜单ID
+    menu_name = mpfun.base64_data(row.menu_name) # 菜单名称
+    parent_id = str(row.parent_id) # 父菜单ID
+    order_num = str(row.order_num) # 显示顺序
+    path = mpfun.base64_data(row.path) # 路由地址
+    component = mpfun.base64_data(row.component) # 组件路径
+    menu_type = row.menu_type # 菜单类型
+    visible = row.visible # 显示状态
+    status = str(row.status) # 状态
+    del_flag = row.del_flag # 删除标志
+
+    # 关键字段合并字符串
+    sign_data = ",".join([menu_id, menu_name, parent_id, order_num, path, component, menu_type, visible, status, del_flag])
+    return sign_data
+
+# 生成HAMC签名值
+def get_sign_hmac(row: SysMenu) -> str:
+    sign_data = get_sign_str(row)
+    return mpfun.sign_data(sign_data)
+
+# 对所有数据进行签名
+def sign_table():
+    print('sign_sys_menu table =====>>>')
+    with get_local_db() as db:
+        rows = db.query(SysMenu).filter(SysMenu.sign == '').all()
+        for row in rows:
+            sign_row(db, row)

+ 80 - 0
common/enc/sys_menu_layer_data.py

@@ -0,0 +1,80 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+from . import mpfun
+from models import *
+from utils import *
+from sqlalchemy.orm import Session
+from database import get_local_db
+
+# 图层菜单表
+
+# 加密和HMAC签名
+def sign_row(db: Session, row: SysMenuLayer) -> None:
+    if row.sign != '':
+        return
+    
+    menu_id = str(row.menu_id) # 菜单ID
+    menu_name = mpfun.base64_data(row.menu_name) # 菜单名称
+    parent_id = str(row.parent_id) # 父菜单ID
+    order_num = str(row.order_num) # 显示顺序
+    path = mpfun.base64_data(row.path) # 路由地址
+    component = mpfun.base64_data(row.component) # 组件路径
+    menu_type = row.menu_type # 菜单类型
+    visible = row.visible # 显示状态
+    status = str(row.status) # 状态
+    del_flag = row.del_flag # 删除标志
+
+    sign_data = ",".join([menu_id, menu_name, parent_id, order_num, path, component, menu_type, visible, status, del_flag])
+    sign_hmac = mpfun.sign_data(sign_data)
+    # print('sign_tbl_post sign_data:', sign_data)
+    # print('sign_tbl_post sign_hmac:', sign_hmac)
+
+    row.sign = sign_hmac
+    
+    db.commit()
+    
+# 比较字段合并字符串是否和MAC值匹配上,调用密码服务器[验证HMAC]接口
+def sign_valid_row(row: SysMenuLayer) -> bool:
+    if row.sign == '':
+        return True
+
+    # 关键字段合并字符串
+    sign_data = get_sign_str(row)
+    # print('sys_post sign_data:', sign_data)
+    
+    # 原HMACSM3数值
+    sign_hmac = row.sign
+    # print('sign_hmac:', sign_hmac)
+
+    return mpfun.hmac_verify(sign_data, sign_hmac)
+
+# 生成待签名的字符串
+def get_sign_str(row: SysMenuLayer) -> str:
+    menu_id = str(row.menu_id) # 菜单ID
+    menu_name = mpfun.base64_data(row.menu_name) # 菜单名称
+    parent_id = str(row.parent_id) # 父菜单ID
+    order_num = str(row.order_num) # 显示顺序
+    path = mpfun.base64_data(row.path) # 路由地址
+    component = mpfun.base64_data(row.component) # 组件路径
+    menu_type = row.menu_type # 菜单类型
+    visible = row.visible # 显示状态
+    status = str(row.status) # 状态
+    del_flag = row.del_flag # 删除标志
+
+    # 关键字段合并字符串
+    sign_data = ",".join([menu_id, menu_name, parent_id, order_num, path, component, menu_type, visible, status, del_flag])
+    return sign_data
+
+# 生成HAMC签名值
+def get_sign_hmac(row: SysMenuLayer) -> str:
+    sign_data = get_sign_str(row)
+    return mpfun.sign_data(sign_data)
+
+# 对所有数据进行签名
+def sign_table():
+    print('sign_sys_menu_layer table =====>>>')
+    with get_local_db() as db:
+        rows = db.query(SysMenuLayer).filter(SysMenuLayer.sign == '').all()
+        for row in rows:
+            sign_row(db, row)

+ 7 - 1
exceptions.py

@@ -44,4 +44,10 @@ class RoleException(Exception):
     def __init__(self, errcode: int, errmsg: str):
         super().__init__(f"Error {errcode}: {errmsg}")
         self.errcode = errcode
-        self.errmsg = errmsg
+        self.errmsg = errmsg
+
+class HmacException(Exception):
+    def __init__(self, code: int, msg: str):
+        super().__init__()
+        self.code = code
+        self.msg = msg

+ 46 - 28
jobs/sign_data_job.py

@@ -4,38 +4,56 @@
 from models.base import *
 from config import settings
 from utils import *
-from database import get_local_db, get_share_db
-from sqlalchemy import text
-from sqlalchemy.sql import func
-from sqlalchemy.orm import Session
 from extensions import logger
-import traceback
-import base64
 from datetime import datetime
-from common.enc import sys_user_data, sys_post_data, sys_role_data, sys_dept_data
+from utils.redis_util import *
+
+from common.enc import sys_user_data, sys_post_data, sys_role_data, sys_dept_data, sys_menu_data, sys_menu_layer_data
 from common.enc import sys_user_role_data, sys_user_post_data, sys_role_dept_data, sys_role_menu_data
 from common.enc import sys_czrz_data
-from utils.redis_util import *
+from common.enc import emergency_contact_info_data
+
 
 # 对数据进行加密处理
 def sign_data_proc():
-    lock_key = "sign_data_proc"
-    if redis_lock(lock_key):
-        logger.info(datetime.now())
-
-        # 系统用户表
-        sys_user_data.sign_table()
-        sys_dept_data.sign_table()
-
-        sys_post_data.sign_table()
-        sys_role_data.sign_table()
-        
-        # # 关联表
-        sys_user_role_data.sign_table()
-        sys_user_post_data.sign_table()
-        sys_role_dept_data.sign_table()
-        # sys_role_menu_data.sign_table()
-        
-        sys_czrz_data.sign_table()
-
-        redis_unlock(lock_key)
+    
+    logger.info(datetime.now())
+
+    # 1.系统表
+    # 系统用户表
+    sys_user_data.sign_table()
+
+    # 系统部门表
+    sys_dept_data.sign_table()
+
+    # 系统岗位表
+    sys_post_data.sign_table()
+    
+    # 系统角色表
+    sys_role_data.sign_table()
+
+    # 系统菜单表
+    sys_menu_data.sign_table()
+    
+    # 系统图层菜单表
+    sys_menu_layer_data.sign_table()
+    
+    # 2.系统关联表
+    # 用户角色表
+    sys_user_role_data.sign_table()
+    
+    # 用户岗位表
+    sys_user_post_data.sign_table()
+    
+    # 角色部门表
+    sys_role_dept_data.sign_table()
+    
+    # 角色菜单表
+    sys_role_menu_data.sign_table()
+
+    # 业务表
+    # 应急预案人员信息表
+    emergency_contact_info_data.sign_table()
+    
+    # 操作日志表
+    sys_czrz_data.sign_table()

+ 12 - 5
models/yjya_base.py

@@ -165,17 +165,24 @@ class EmergencyDoc(Base):
         orm_mode = True
 
 
+'''
+应急预案人员信息
+'''
 class EmergencyContactInfo(Base):
     __tablename__ = 'emergency_contact_info'
 
     id = Column(Integer, autoincrement=True, primary_key=True)
     unit_id = Column(Integer, nullable=False, comment='单位ID')
-    unit_name = Column(String(255), nullable=False, comment='单位名称')
-    contact_name = Column(String(255), nullable=False, comment='联系人')
-    position = Column(String(255), comment='职务')
-    yue_gov_ease_phone = Column(String(20), comment='粤政易手机号码')
+    unit_name = Column(String, nullable=False, default='', comment='单位名称')
+    contact_name = Column(String, nullable=False, default='', comment='联系人')
+    position = Column(String, default='', comment='职务')
+    yue_gov_ease_phone = Column(String, default='', comment='粤政易手机号码')
     create_time = Column(DateTime, default=datetime.now, comment='数据创建时间')
     update_time = Column(DateTime, default=datetime.now, onupdate=datetime.now, comment='数据更新时间')
     create_dept = Column(BigInteger, default=None, comment='创建部门')
     create_by = Column(BigInteger, default=None, comment='创建者')
-    del_flag = Column(String(1), default='0', comment='删除标志(0代表存在 2代表删除)')
+    del_flag = Column(String, default='0', comment='删除标志(0代表存在 2代表删除)')
+    sign = Column(String, server_default='', default='', comment='HMACSM3数值')
+    
+    class Config:
+        orm_mode = True

+ 2 - 1
routers/api/eventManagement/event.py

@@ -23,6 +23,7 @@ import base64
 from config import settings
 from extensions import logger
 import os
+from common.enc import mpfun
 
 router = APIRouter()
 
@@ -940,7 +941,7 @@ async def send_emergency_plan_task_by_yzy(
         if contact_row is None:
             continue
         
-        yzy_account = contact_row.yue_gov_ease_phone
+        yzy_account = mpfun.dec_data(contact_row.yue_gov_ease_phone)
         nick_name = contact_row.contact_name
         
         yzy_user_row = db.query(YzyOrgUserEntity).filter(YzyOrgUserEntity.account == yzy_account).first()

+ 83 - 51
routers/api/layerConfiguration/__init__.py

@@ -13,6 +13,10 @@ from utils.ry_system_util import *
 import json
 from sqlalchemy.sql import func
 from common.auth_user import *
+from common.enc import mpfun, sys_menu_data, sys_menu_layer_data
+import traceback
+from common.db import db_czrz
+from exceptions import HmacException
 
 router = APIRouter()
 
@@ -470,19 +474,21 @@ class SysMuneCreateForm(BaseModel):
     queryParam:str=None
     status:str
     visible:str
-    layer_template:str
+    layer_template:str=None
 
 
 @router.post('/create')
 async def create(
-        form_data: SysMuneCreateForm,
-        db: Session = Depends(get_db),
-        body=Depends(remove_xss_json),
-        user_id=Depends(valid_access_token)
+    request: Request,
+    form_data: SysMuneCreateForm,
+    db: Session = Depends(get_db),
+    body=Depends(remove_xss_json),
+    auth_user: AuthUser = Depends(find_auth_user),
+    user_id=Depends(valid_access_token)
 ):
     try:
         # 开始事务
-        db.begin()
+        # db.begin()
 
         # 创建新的菜单项
         new_menu = SysMenu(
@@ -525,7 +531,8 @@ async def create(
         db.add(new_menu_layer)
 
         # 提交事务之前刷新new_menu以确保menu_id被数据库生成
-        db.flush()  # 使用flush而不是commit,这样可以保存数据但不结束事务
+        # db.flush()  # 使用flush而不是commit,这样可以保存数据但不结束事务
+        
         db.refresh(new_menu)  # 刷新new_menu对象以获取数据库生成的menu_id
         new_menu_layer.menu_id = new_menu.menu_id  # 现在可以设置new_menu_layer的menu_id了
 
@@ -535,12 +542,19 @@ async def create(
         # 提交事务
         db.commit()
 
+        sys_menu_data.sign_table()
+        sys_menu_layer_data.sign_table()
+
+        db_czrz.log(db, auth_user, "系统管理", f"后台管理新建地图菜单【{form_data.menuName}】成功", request.client.host)
+
         return {
             "code": 200,
             "data": new_menu_layer.menu_id,  # 返回新创建的SysMenuLayer的ID
             "msg": "操作成功"
         }
     except Exception as e:
+        traceback.print_exc()
+
         # 如果发生异常,回滚事务
         db.rollback()
         raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=str(e))
@@ -565,6 +579,7 @@ class SysMuneUpdateForm(BaseModel):
 @router.put('')
 async def update(
     request: Request,
+    auth_user: AuthUser = Depends(find_auth_user),
     # form_data: SysMuneUpdateForm,
     db: Session = Depends(get_db),
     body = Depends(remove_xss_json),
@@ -572,44 +587,44 @@ async def update(
 ):
 
     try:
-        db.begin()
-        query = db.query(SysMenu)
-        query = query.filter(SysMenu.menu_id == body['menuId'])
-        query = query.filter(SysMenu.del_flag != '2')
-        menu = query.first()
-        if not menu:
-            detail = "菜单不存在"
-            raise HTTPException(status_code=404, detail="菜单不存在")
-
-        # 更新字段,排除主键和不可更新的字段
-        if 'component' in body:
-            menu.component=body['component']
-        if 'icon' in body:
-            menu.icon=body['icon']
-        if 'isCache' in body:
-            menu.is_cache=body['isCache']
-        if 'isFrame' in body:
-            menu.is_frame=body['isFrame']
-        if 'menuName' in body:
-            menu.menu_name=body['menuName']
-        if 'menuType' in body:
-            menu.menu_type=body['menuType']
-        if 'orderNum' in body:
-            menu.order_num=body['orderNum']
-        if 'parentId' in body:
-            menu.parent_id=body['parentId']
-        if 'path' in body:
-            menu.path=body['path']
-        if 'perms' in body:
-            menu.perms=body['perms']
-        if 'queryParam' in body:
-            menu.query_param=body['queryParam']
-        if 'status' in body:
-            menu.status=body['status']
-        if 'visible' in body:
-            menu.visible=body['visible']
-        if user_id:
-            menu.create_by = user_id
+        # db.begin()
+        # query = db.query(SysMenuLayer)
+        # query = query.filter(SysMenuLayer.menu_id == body['menuId'])
+        # query = query.filter(SysMenuLayer.del_flag != '2')
+        # menu = query.first()
+        # if not menu:
+        #     detail = "菜单不存在"
+        #     raise HTTPException(status_code=404, detail="菜单不存在")
+
+        # # 更新字段,排除主键和不可更新的字段
+        # if 'component' in body:
+        #     menu.component=body['component']
+        # if 'icon' in body:
+        #     menu.icon=body['icon']
+        # if 'isCache' in body:
+        #     menu.is_cache=body['isCache']
+        # if 'isFrame' in body:
+        #     menu.is_frame=body['isFrame']
+        # if 'menuName' in body:
+        #     menu.menu_name=body['menuName']
+        # if 'menuType' in body:
+        #     menu.menu_type=body['menuType']
+        # if 'orderNum' in body:
+        #     menu.order_num=body['orderNum']
+        # if 'parentId' in body:
+        #     menu.parent_id=body['parentId']
+        # if 'path' in body:
+        #     menu.path=body['path']
+        # if 'perms' in body:
+        #     menu.perms=body['perms']
+        # if 'queryParam' in body:
+        #     menu.query_param=body['queryParam']
+        # if 'status' in body:
+        #     menu.status=body['status']
+        # if 'visible' in body:
+        #     menu.visible=body['visible']
+        # if user_id:
+        #     menu.create_by = user_id
         # for field, value in menu_data.items():
         #     if field != 'menu_id' and field in menu_to_update.__dict__:
         #         setattr(menu_to_update, field, value)
@@ -653,16 +668,25 @@ async def update(
             menu.status = body['status']
         if 'visible' in body:
             menu.visible = body['visible']
-        if user_id:
-            menu.create_by = user_id
-        if user_id:
-            menu.layer_template =body['layer_template']
+        if 'layer_template' in body:
+            menu.layer_template = body['layer_template']
+        
+        menu.update_by = user_id
+        menu.update_time = datetime.now()
+        menu.sign = sys_menu_layer_data.get_sign_hmac(menu)
+        
         db.commit()
+
+        db_czrz.log(db, auth_user, "系统管理", f"后台管理更新地图菜单【{body['menuName']}】成功", request.client.host)
+
+        
         return {
             "code": 200,
             "msg": "菜单更新成功"
         }
     except Exception as e:
+        traceback.print_exc()
+
         # db.rollback()
         if str(e)=='':
             e = detail
@@ -672,9 +696,11 @@ async def update(
 
 @router.delete('/{menu_id}')
 async def delete(
+    request: Request,
     menu_id: int,
     db: Session = Depends(get_db),
     body = Depends(remove_xss_json),
+    auth_user: AuthUser = Depends(find_auth_user),
     user_id = Depends(valid_access_token)
 ):
     try:
@@ -701,15 +727,21 @@ async def delete(
         if not menu_to_delete:
             detail = "菜单不存在"
             raise HTTPException(status_code=404, detail="菜单不存在")
-        menu_to_delete.create_by = user_id
+        menu_to_delete.update_by = user_id
+        menu_to_delete.update_time = datetime.now()
         menu_to_delete.del_flag = '2'
-
+        menu_to_delete.sign = sys_menu_layer_data.get_sign_hmac(menu_to_delete)
         db.commit()
+
+        db_czrz.log(db, auth_user, "系统管理", f"后台管理删除菜单【{menu_to_delete.menu_name}】成功", request.client.host)
+
         return {
             "code": 200,
             "msg": "菜单删除成功"
         }
     except Exception as e:
+        traceback.print_exc()
+        
         db.rollback()
         if str(e)=='':
             e = detail

+ 4 - 1
routers/prod_api/system/dept/__init__.py

@@ -291,8 +291,10 @@ async def dept_info_update(
             dept.phone = body['phone']
         if 'leader' in body:
             dept.leader = body['leader']
+
             leader_user_info = user_id_get_user_info(db, dept.leader)
-            dept.leader_name = leader_user_info.nick_name
+            if leader_user_info is not None:
+                dept.leader_name = leader_user_info.nick_name
         
         dept_parent = dept_id_get_dept_info(db, dept.parentId)
         dept.parent_name = dept_parent.dept_name,
@@ -311,6 +313,7 @@ async def dept_info_update(
             "msg": "部门更新成功"
         }
     except Exception as e:
+        traceback.print_exc()
         db.rollback()
         if str(e)=='':
             e = detail

+ 70 - 18
routers/prod_api/system/menu/__init__.py

@@ -12,8 +12,11 @@ from utils import *
 from utils.ry_system_util import *
 import json
 from sqlalchemy.sql import func
+from common.enc import mpfun, sys_menu_data, sys_menu_layer_data
 from common.auth_user import *
+from common.db import db_czrz
 import traceback
+from exceptions import HmacException
 
 
 router = APIRouter()
@@ -119,12 +122,16 @@ async def getRouters(request: Request, db: Session = Depends(get_db),
         query = query.filter(SysMenu.menu_id!=11655)
         query = query.filter(SysMenu.del_flag != '2')
         query = query.order_by(SysMenu.order_num.asc())
-        menus =query.all()  # 顶级菜单
+        menus = query.all()  # 顶级菜单
 
         # 递归函数用于构建树形结构
         def build_menu_tree(menus, parent_menu):
             menu_tree = []  # 初始化一个列表来存储菜单树结构
             for menu in menus:
+
+                if sys_menu_data.sign_valid_row(menu) == False:
+                    raise HmacException(500, "系统菜单表验证异常,已被非法篡改")
+
                 component =  'Layout'
                 if menu.menu_type=='M' and parent_menu:
                     component = 'ParentView'
@@ -186,6 +193,13 @@ async def getRouters(request: Request, db: Session = Depends(get_db),
             "msg": "操作成功",
             "data": routers #[router.dict() for router in routers]  # 如果没有顶级菜单,返回空列表
         }
+    
+    except HmacException as e:
+        return {
+            "code": e.code,
+            "msg": e.msg
+        }
+    
     except Exception as e:
         traceback.print_exc()
         raise HTTPException(status_code=500, detail=f"Internal server error: {str(e)}")
@@ -250,6 +264,10 @@ async def getRouters(request: Request, db: Session = Depends(get_db),
         def build_menu_tree(menus, parent_menu):
             menu_tree = []  # 初始化一个列表来存储菜单树结构
             for menu in menus:
+
+                if sys_menu_layer_data.sign_valid_row(menu) == False:
+                    raise HmacException(500, "系统图层菜单表验证异常,已被非法篡改")
+                
                 menu_data = {
                     "component": menu.component or 'Layout',
                     "isVideo":False,
@@ -313,6 +331,13 @@ async def getRouters(request: Request, db: Session = Depends(get_db),
             "msg": "操作成功",
             "data": routers  # [router.dict() for router in routers]  # 如果没有顶级菜单,返回空列表
         }
+
+    except HmacException as e:
+        return {
+            "code": e.code,
+            "msg": e.msg
+        }
+    
     except Exception as e:
         traceback.print_exc()
         raise HTTPException(status_code=500, detail=f"Internal server error: {str(e)}")
@@ -523,35 +548,44 @@ async def create(
     form_data: SysMuneCreateForm,
     db: Session = Depends(get_db),
     body = Depends(remove_xss_json),
+    auth_user: AuthUser = Depends(find_auth_user),
     user_id = Depends(valid_access_token)
 ):
 
     try:
         new_menu = SysMenu(
-                            menu_name = form_data.menuName,
-                            parent_id = form_data.parentId,
-                            order_num = form_data.orderNum,
-                            path = form_data.path,
-                            is_frame = int(form_data.isFrame),
-                            is_cache = int(form_data.isCache),
-                            menu_type = form_data.menuType,
-                            visible = form_data.visible,
-                            status = form_data.status,
-                            icon = form_data.icon,
-                            component= form_data.component,
-                            perms=form_data.perms,
-                            query_param=form_data.queryParam,
-                            create_by = user_id
-                           )
+            menu_name = form_data.menuName,
+            parent_id = form_data.parentId,
+            order_num = form_data.orderNum,
+            path = form_data.path,
+            is_frame = int(form_data.isFrame),
+            is_cache = int(form_data.isCache),
+            menu_type = form_data.menuType,
+            visible = form_data.visible,
+            status = form_data.status,
+            icon = form_data.icon,
+            component= form_data.component,
+            perms=form_data.perms,
+            query_param=form_data.queryParam,
+            create_by = user_id
+        )
         db.add(new_menu)
         db.commit()
         db.refresh(new_menu)
+
+        sys_menu_data.sign_table()
+
+        db_czrz.log(db, auth_user, "系统管理", f"后台管理新建菜单【{form_data.menuName}】成功", request.client.host)
+
         return {
             "code": 200,
             "data": None,
             "msg": "操作成功"
         }
     except Exception as e:
+        
+        traceback.print_exc()
+
         db.rollback()
         raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=str(e))
 
@@ -578,6 +612,7 @@ async def update(
     # form_data: SysMuneUpdateForm,
     db: Session = Depends(get_db),
     body = Depends(remove_xss_json),
+    auth_user: AuthUser = Depends(find_auth_user),
     user_id = Depends(valid_access_token)
 ):
 
@@ -618,19 +653,28 @@ async def update(
         if 'visible' in body:
             menu.visible=body['visible']
         if user_id:
-            menu.create_by = user_id
+            menu.update_by = user_id
+        
+        menu.update_time = datetime.now()
+        menu.sign = sys_menu_data.get_sign_hmac(menu)
+
         # for field, value in menu_data.items():
         #     if field != 'menu_id' and field in menu_to_update.__dict__:
         #         setattr(menu_to_update, field, value)
         #
         # db.add(menu_to_update)
         db.commit()
+
+        db_czrz.log(db, auth_user, "系统管理", f"后台管理更新菜单【{body['menuName']}】成功", request.client.host)
+
         return {
             "code": 200,
             "msg": "菜单更新成功"
         }
     except Exception as e:
         # db.rollback()
+        traceback.print_exc()
+
         if str(e)=='':
             e = detail
         raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=str(e))
@@ -641,6 +685,7 @@ async def delete(
     menu_id: int,
     db: Session = Depends(get_db),
     body = Depends(remove_xss_json),
+    auth_user: AuthUser = Depends(find_auth_user),
     user_id = Depends(valid_access_token)
 ):
     try:
@@ -652,15 +697,22 @@ async def delete(
         if not menu_to_delete:
             detail = "菜单不存在"
             raise HTTPException(status_code=404, detail="菜单不存在")
-        menu_to_delete.create_by = user_id
         menu_to_delete.del_flag='2'
+        menu_to_delete.update_by = user_id
+        menu_to_delete.update_time = datetime.now()
+        menu_to_delete.sign = sys_menu_data.get_sign_hmac(menu_to_delete)
+
         # db.delete(menu_to_delete)
         db.commit()
+
+        db_czrz.log(db, auth_user, "系统管理", f"后台管理删除菜单【{menu_to_delete.menu_name}】成功", request.client.host)
+
         return {
             "code": 200,
             "msg": "菜单删除成功"
         }
     except Exception as e:
+        traceback.print_exc()
         db.rollback()
         if str(e)=='':
             e = detail

+ 3 - 3
routers/prod_api/system/role/__init__.py

@@ -113,7 +113,7 @@ async def roleupdate(
 
         sys_role_menu_data.sign_table()
 
-        db_czrz.log(db, auth_user, "系统管理", f"后台管修改用户角色【{body['roleName']}】成功", request.client.host)
+        db_czrz.log(db, auth_user, "系统管理", f"后台管修改用户角色【{body['roleName']}】成功", request.client.host)
 
         return {"code": 200, "msg": "更新成功", "data": None}
 
@@ -197,7 +197,7 @@ async def roleupdate(
 
         sys_role_data.sign_table()
 
-        db_czrz.log(db, auth_user, "系统管理", f"后台管修改用户角色状态【{body['role_name']}】成功", request.client.host)
+        db_czrz.log(db, auth_user, "系统管理", f"后台管修改用户角色状态【{body['role_name']}】成功", request.client.host)
 
         return {"code": 200, "msg": "更新成功", "data": None}
 
@@ -442,7 +442,7 @@ async def cancel_user_role(
         query.delete()
         db.commit()
         sys_user_role_data.sign_table()
-        
+
         user_info = user_id_get_user_info(db, user_id)
 
         db_czrz.log(db, auth_user, "系统管理", f"后台管用户角色删除用户【{user_info.nick_name}】成功", request.client.host)