236 lines
9.6 KiB
Python
236 lines
9.6 KiB
Python
# -*- coding: utf-8 -*-
|
|
"""script_engine.init —— 模块初始化与业务函数注册。"""
|
|
from ahserver.serverenv import ServerEnv
|
|
from sqlor.dbpools import DBPools
|
|
from appPublic.uniqueID import getID
|
|
from appPublic.timeUtils import curDateString
|
|
from script_engine.engine import validate_script as _validate_content, execute_script_content as _execute_content, VALID_SCRIPT_TYPES
|
|
|
|
|
|
def _dbname():
|
|
return ServerEnv().get_module_dbname('script_engine')
|
|
|
|
|
|
def _ok(data=None, message='ok'):
|
|
return {'code': 0, 'message': message, 'field': '', 'detail': '', 'data': data}
|
|
|
|
|
|
def _err(code, message, field='', detail=''):
|
|
return {'code': code, 'message': message, 'field': field, 'detail': detail}
|
|
|
|
|
|
def _clean_str(value, default=''):
|
|
if value is None:
|
|
return default
|
|
s = str(value).strip()
|
|
return s if s else default
|
|
|
|
|
|
def _validate_input(script_name, script_type, content):
|
|
if not script_name:
|
|
return False, 'script_name', '脚本名称不能为空'
|
|
if len(script_name) > 100:
|
|
return False, 'script_name', '脚本名称长度不能超过 100'
|
|
if script_type not in VALID_SCRIPT_TYPES:
|
|
return False, 'script_type', '不支持的脚本类型: %s' % script_type
|
|
if not content or not content.strip():
|
|
return False, 'content', '脚本内容不能为空'
|
|
if len(content) > 65535:
|
|
return False, 'content', '脚本内容长度不能超过 65535'
|
|
ok, err = _validate_content(content, script_type)
|
|
if not ok:
|
|
return False, 'content', err
|
|
return True, '', ''
|
|
|
|
|
|
async def create_script(request, params_kw):
|
|
try:
|
|
params = params_kw or {}
|
|
script_name = _clean_str(params.get('script_name'))
|
|
script_type = _clean_str(params.get('script_type'), '0')
|
|
content = _clean_str(params.get('content'))
|
|
description = _clean_str(params.get('description'))
|
|
status = _clean_str(params.get('status'), '1')
|
|
ok, field, msg = _validate_input(script_name, script_type, content)
|
|
if not ok:
|
|
return _err(400, msg, field, 'create_script: 参数校验失败')
|
|
dbname = _dbname()
|
|
db = DBPools()
|
|
now = curDateString()
|
|
new_id = getID()
|
|
ns = {'id': new_id, 'script_name': script_name, 'script_type': script_type, 'content': content, 'description': description, 'status': status, 'created_at': now, 'updated_at': now}
|
|
async with db.sqlorContext(dbname) as sor:
|
|
await sor.C('script', ns)
|
|
return _ok({'id': new_id}, '创建成功')
|
|
except Exception as e:
|
|
from traceback import format_exc
|
|
return _err(500, '创建失败: %s' % str(e), '', format_exc())
|
|
|
|
|
|
async def update_script(request, params_kw):
|
|
try:
|
|
params = params_kw or {}
|
|
script_id = _clean_str(params.get('id'))
|
|
if not script_id:
|
|
return _err(400, '缺少脚本ID', 'id', 'update_script: id 必填')
|
|
script_name = _clean_str(params.get('script_name'))
|
|
script_type = _clean_str(params.get('script_type'), '0')
|
|
content = _clean_str(params.get('content'))
|
|
description = _clean_str(params.get('description'))
|
|
status = _clean_str(params.get('status'), '1')
|
|
ok, field, msg = _validate_input(script_name, script_type, content)
|
|
if not ok:
|
|
return _err(400, msg, field, 'update_script: 参数校验失败')
|
|
dbname = _dbname()
|
|
db = DBPools()
|
|
async with db.sqlorContext(dbname) as sor:
|
|
rows = await sor.R('script', {'id': script_id})
|
|
if not rows:
|
|
return _err(404, '脚本不存在', 'id', 'update_script: 记录不存在')
|
|
upd = {'script_name': script_name, 'script_type': script_type, 'content': content, 'description': description, 'status': status, 'updated_at': curDateString()}
|
|
upd['id'] = script_id
|
|
await sor.U('script', upd)
|
|
return _ok({'id': script_id}, '更新成功')
|
|
except Exception as e:
|
|
from traceback import format_exc
|
|
return _err(500, '更新失败: %s' % str(e), '', format_exc())
|
|
|
|
|
|
async def delete_script(request, params_kw):
|
|
try:
|
|
params = params_kw or {}
|
|
script_id = _clean_str(params.get('id'))
|
|
if not script_id:
|
|
return _err(400, '缺少脚本ID', 'id', 'delete_script: id 必填')
|
|
dbname = _dbname()
|
|
db = DBPools()
|
|
async with db.sqlorContext(dbname) as sor:
|
|
rows = await sor.R('script', {'id': script_id})
|
|
if not rows:
|
|
return _err(404, '脚本不存在', 'id', 'delete_script: 记录不存在')
|
|
await sor.D('script', {'id': script_id})
|
|
return _ok({'id': script_id}, '删除成功')
|
|
except Exception as e:
|
|
from traceback import format_exc
|
|
return _err(500, '删除失败: %s' % str(e), '', format_exc())
|
|
|
|
|
|
async def get_script(request, params_kw):
|
|
try:
|
|
params = params_kw or {}
|
|
script_id = _clean_str(params.get('id'))
|
|
if not script_id:
|
|
return _err(400, '缺少脚本ID', 'id', 'get_script: id 必填')
|
|
dbname = _dbname()
|
|
db = DBPools()
|
|
async with db.sqlorContext(dbname) as sor:
|
|
rows = await sor.R('script', {'id': script_id})
|
|
if not rows:
|
|
return _err(404, '脚本不存在', 'id', 'get_script: 记录不存在')
|
|
rec = dict(rows[0])
|
|
return _ok(rec, '查询成功')
|
|
except Exception as e:
|
|
from traceback import format_exc
|
|
return _err(500, '查询失败: %s' % str(e), '', format_exc())
|
|
|
|
|
|
async def list_scripts(request, params_kw):
|
|
try:
|
|
params = params_kw or {}
|
|
page = int(params.get('page', 1) or 1)
|
|
rows = int(params.get('rows', 20) or 20)
|
|
if page < 1:
|
|
page = 1
|
|
if rows < 1 or rows > 200:
|
|
rows = 20
|
|
keyword = _clean_str(params.get('script_name'))
|
|
script_type = _clean_str(params.get('script_type'))
|
|
status = _clean_str(params.get('status'))
|
|
conds = []
|
|
ns = {'page': page, 'rows': rows, 'sort': 'created_at desc'}
|
|
if keyword:
|
|
conds.append('script_name like ${keyword}$')
|
|
ns['keyword'] = '%%%s%%' % keyword
|
|
if script_type:
|
|
conds.append('script_type = ${script_type}$')
|
|
ns['script_type'] = script_type
|
|
if status:
|
|
conds.append('status = ${status}$')
|
|
ns['status'] = status
|
|
where = (' where ' + ' and '.join(conds)) if conds else ''
|
|
sql = 'select id, script_name, script_type, description, status, created_at, updated_at from script%s' % where
|
|
dbname = _dbname()
|
|
db = DBPools()
|
|
async with db.sqlorContext(dbname) as sor:
|
|
result = await sor.sqlExe(sql, ns)
|
|
total = result.get('total', 0) if isinstance(result, dict) else len(result or [])
|
|
data = result.get('rows', []) if isinstance(result, dict) else (result or [])
|
|
return _ok({'list': data, 'total': total}, '查询成功')
|
|
except Exception as e:
|
|
from traceback import format_exc
|
|
return _err(500, '列表查询失败: %s' % str(e), '', format_exc())
|
|
|
|
|
|
async def execute_script(request, params_kw):
|
|
try:
|
|
params = params_kw or {}
|
|
script_id = _clean_str(params.get('id'))
|
|
content = None
|
|
script_type = '0'
|
|
if script_id:
|
|
dbname = _dbname()
|
|
db = DBPools()
|
|
async with db.sqlorContext(dbname) as sor:
|
|
rows = await sor.R('script', {'id': script_id})
|
|
if not rows:
|
|
return _err(404, '脚本不存在', 'id', 'execute_script: 记录不存在')
|
|
content = rows[0].content
|
|
script_type = str(rows[0].script_type or '0')
|
|
else:
|
|
content = _clean_str(params.get('content'))
|
|
script_type = _clean_str(params.get('script_type'), '0')
|
|
if not content:
|
|
return _err(400, '脚本内容不能为空', 'content', 'execute_script: 无脚本内容')
|
|
ok, field, msg = _validate_input('t', script_type, content)
|
|
if not ok:
|
|
return _err(400, msg, field, 'execute_script: 校验失败,不执行')
|
|
run_params = params.get('params') or {}
|
|
result = _execute_content(content, script_type, run_params)
|
|
return _ok(result, '执行成功')
|
|
except NotImplementedError as e:
|
|
return _err(501, str(e), 'script_type', 'execute_script: 该类型暂不支持执行')
|
|
except Exception as e:
|
|
from traceback import format_exc
|
|
return _err(500, '执行失败: %s' % str(e), '', format_exc())
|
|
|
|
|
|
async def validate_script_api(request, params_kw):
|
|
try:
|
|
params = params_kw or {}
|
|
content = _clean_str(params.get('content'))
|
|
script_type = _clean_str(params.get('script_type'), '0')
|
|
if not content:
|
|
return _err(400, '脚本内容不能为空', 'content', 'validate_script: 无脚本内容')
|
|
ok, field, msg = _validate_input('t', script_type, content)
|
|
if not ok:
|
|
return _err(400, msg, field, 'validate_script: 校验失败')
|
|
return _ok({'valid': True}, '校验通过')
|
|
except Exception as e:
|
|
from traceback import format_exc
|
|
return _err(500, '校验失败: %s' % str(e), '', format_exc())
|
|
|
|
|
|
def load_script_engine():
|
|
env = ServerEnv()
|
|
env.create_script = create_script
|
|
env.update_script = update_script
|
|
env.delete_script = delete_script
|
|
env.get_script = get_script
|
|
env.list_scripts = list_scripts
|
|
env.execute_script = execute_script
|
|
env.validate_script_api = validate_script_api
|
|
env.create_scripts = create_script
|
|
env.update_scripts = update_script
|
|
env.delete_scripts = delete_script
|
|
return env
|