first commit
This commit is contained in:
159
lib/validators.py
Normal file
159
lib/validators.py
Normal file
@@ -0,0 +1,159 @@
|
||||
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
|
||||
Reference in New Issue
Block a user