160 lines
4.8 KiB
Python
160 lines
4.8 KiB
Python
import re
|
|
import logging
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
USER_ID_PATTERN = re.compile(r'^[a-zA-Z0-9]+$')
|
|
|
|
|
|
def validate_user_id(user_id):
|
|
if not user_id:
|
|
return False, "人员ID不能为空"
|
|
if not USER_ID_PATTERN.match(user_id):
|
|
return False, "人员ID仅支持大小写英文字母和数字"
|
|
if len(user_id) > 50:
|
|
return False, "人员ID长度不能超过50"
|
|
return True, ""
|
|
|
|
|
|
def validate_user_name(user_name):
|
|
if not user_name:
|
|
return False, "人员姓名不能为空"
|
|
if len(user_name) > 100:
|
|
return False, "人员姓名长度不能超过100"
|
|
return True, ""
|
|
|
|
|
|
def validate_height(height):
|
|
if height is None or height == "":
|
|
return True, None
|
|
try:
|
|
h = float(height)
|
|
if 0.1 <= h <= 10.0:
|
|
return True, round(h, 1)
|
|
return False, f"高度 {height} 超出有效范围 0.1~10.0"
|
|
except (ValueError, TypeError):
|
|
return False, f"高度 {height} 不是有效数值"
|
|
|
|
|
|
def validate_noise_level(level):
|
|
if level is None or level == "":
|
|
return True, 0
|
|
try:
|
|
n = int(level)
|
|
if 0 <= n <= 10:
|
|
return True, n
|
|
return False, f"噪声强度 {level} 超出有效范围 0~10"
|
|
except (ValueError, TypeError):
|
|
return False, f"噪声强度 {level} 不是有效整数"
|
|
|
|
|
|
def validate_rotate(min_val, max_val):
|
|
def _clamp(v):
|
|
try:
|
|
v = int(v)
|
|
return max(-180, min(180, v))
|
|
except (ValueError, TypeError):
|
|
return 0
|
|
r_min = _clamp(min_val) if min_val not in (None, "") else 0
|
|
r_max = _clamp(max_val) if max_val not in (None, "") else 0
|
|
return True, (r_min, r_max)
|
|
|
|
|
|
def validate_match_mode(mode):
|
|
if mode in ('upload', 'id', 'name', 'auto'):
|
|
return True, ""
|
|
return False, f"匹配模式 '{mode}' 无效,支持: upload/id/name/auto"
|
|
|
|
|
|
def validate_docx_name(name):
|
|
if not name:
|
|
return False, "文件名不能为空"
|
|
if not name.lower().endswith('.docx'):
|
|
return False, "仅支持.docx格式"
|
|
return True, ""
|
|
|
|
|
|
def validate_docx_size(data_bytes, max_bytes):
|
|
if not isinstance(data_bytes, (bytes, bytearray)):
|
|
return False, "文档数据无效"
|
|
if len(data_bytes) > max_bytes:
|
|
return False, f"文档大小 {len(data_bytes)} 字节超过限制 {max_bytes} 字节"
|
|
return True, ""
|
|
|
|
|
|
def validate_image_size(data_bytes, max_bytes):
|
|
if not isinstance(data_bytes, (bytes, bytearray)):
|
|
return False, "图片数据无效"
|
|
if len(data_bytes) > max_bytes:
|
|
return False, f"图片大小 {len(data_bytes)} 字节超过限制 {max_bytes} 字节"
|
|
return True, ""
|
|
|
|
|
|
def validate_capture_group(group):
|
|
if group is None or group == "":
|
|
return False, "捕获组序号不能为空"
|
|
try:
|
|
g = int(group)
|
|
except (ValueError, TypeError):
|
|
return False, f"捕获组序号 '{group}' 不是整数"
|
|
if g < 1:
|
|
return False, "捕获组序号禁止为 0 或负数,必须 >=1"
|
|
return True, g
|
|
|
|
|
|
def validate_rule(rule):
|
|
errors = []
|
|
if not rule.get('name'):
|
|
errors.append("规则名称不能为空")
|
|
pattern = rule.get('pattern')
|
|
if not pattern:
|
|
errors.append("规则正则表达式不能为空")
|
|
else:
|
|
try:
|
|
re.compile(pattern)
|
|
except re.error as e:
|
|
errors.append(f"正则表达式非法: {e}")
|
|
valid, msg_or_val = validate_capture_group(rule.get('capture_group'))
|
|
if not valid:
|
|
errors.append(msg_or_val)
|
|
cell_mode = rule.get('cell_mode', 'single')
|
|
if cell_mode not in ('single', 'horizontal', 'vertical'):
|
|
errors.append(f"表格方式 '{cell_mode}' 无效")
|
|
cell_match = rule.get('cell_match', 'partial')
|
|
if cell_match not in ('partial', 'whole'):
|
|
errors.append(f"匹配方式 '{cell_match}' 无效")
|
|
return errors
|
|
|
|
|
|
def validate_sign_request(params):
|
|
errors = []
|
|
|
|
valid, msg = validate_docx_name(params.get('docx_name', ''))
|
|
if not valid:
|
|
errors.append(msg)
|
|
|
|
valid, msg = validate_match_mode(params.get('match_mode', ''))
|
|
if not valid:
|
|
errors.append(msg)
|
|
|
|
stamps = params.get('stamps', [])
|
|
if params.get('match_mode') != 'auto' and not stamps:
|
|
errors.append("非auto模式必须提供盖章项列表")
|
|
|
|
if len(stamps) > 100:
|
|
errors.append("盖章项不能超过100个")
|
|
|
|
height = params.get('height')
|
|
if height is not None and height != "":
|
|
valid, _ = validate_height(height)
|
|
if not valid:
|
|
errors.append(f"全局高度无效: {validate_height(height)[1]}")
|
|
|
|
noise = params.get('noise_level')
|
|
if noise is not None and noise != "":
|
|
valid, _ = validate_noise_level(noise)
|
|
if not valid:
|
|
errors.append(f"全局噪声无效: {validate_noise_level(noise)[1]}")
|
|
|
|
return errors
|