diff --git a/views/__init__.py b/views/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..b269c792a75358fd1274edae6869bd21ac6dbf4a --- /dev/null +++ b/views/__init__.py @@ -0,0 +1,21 @@ +import importlib +import os + +from sanic import Blueprint + + +class Views(object): + + def __init__(self): + self.list = list() + path = os.path.dirname(os.path.realpath(__file__)) + + for i in os.listdir(path): + if not i.endswith('_view.py'): + continue + base = i.split('.')[0] + module = 'views.' + base + imp = importlib.import_module(module) + self.list.append(getattr(imp, 'bp')) + + self.bp = Blueprint.group(self.list) diff --git a/views/auth_view.py b/views/auth_view.py new file mode 100644 index 0000000000000000000000000000000000000000..713cb4c639d85f53216e823064e7eb3dd388d247 --- /dev/null +++ b/views/auth_view.py @@ -0,0 +1,165 @@ +from sanic import Blueprint, response + +from app.conf import conf +from common.http import rsp +from services.auth_service import login_auth, check_user, register_user, get_user_info, check_admin, \ + refresh_private_token, get_user_list, update_user_info, apply_senior_role, upgrade_role, \ + delete_user, get_operator_log, update_user_role, get_review_count, logout_jwt, read_auth, get_reviewers +from views.utils import check_args, ERROR_EMPTY_ARG, ERROR_LACK_ARGS + +bp = Blueprint('auth', url_prefix='api/user') + + +@bp.post("/login") +async def login(request): + args = ['name', 'password'] + result, ok = check_args(args, request.json) + if not ok: + return result + result, ok = await check_user(request.json) + if not ok: + return rsp(code=500, msg=result) + return rsp(data=result) + + +@bp.post("/logout") +@login_auth +async def logout(_, user_infos): + result, ok = await logout_jwt(user_infos['user_name']) + if not ok: + return rsp(code=500, msg=result) + return rsp() + + +@bp.get('/anolis/login') +async def login(request): + return response.redirect(conf.config['LOGIN_URL']) + + +@bp.get('/anolis/logout') +async def logout(request): + return response.redirect(conf.config['LOGOUT_URL']) + + +@bp.post('/register') +async def register(request): + args = ['nick_name', 'email', 'password'] + result, ok = check_args(args, request.json) + if not ok: + return result + result, ok = await register_user(request.json) + if not ok: + return rsp(code=500, msg=result) + return rsp() + + +@bp.get('/info') +@login_auth +async def user_info(_, user_infos): + return rsp(data=await get_user_info(user_infos['user_name'])) + + +@bp.get('/token') +@login_auth +async def refresh_token(_, user_infos): + token = await refresh_private_token(user_infos['user_name']) + return rsp(data=token) + + +@bp.get('/user-list', ignore_body=True) +@login_auth +@check_admin +async def get_user_infos(request, user_infos): + page_num = int(request.args.get('page_num')) if request.args.get('page_num') else 1 + page_size = int(request.args.get('page_size')) if request.args.get('page_size') else 10 + result = await get_user_list(request.args, page_num, page_size) + return rsp(paginate=result) + + +@bp.post('/update') +@login_auth +async def update(request, user_infos): + if not request.json: + return rsp(code=400, msg=ERROR_EMPTY_ARG) + data = await update_user_info(user_infos['user_name'], request.json) + return rsp(data=data) + + +@bp.post('/apply') +@login_auth +async def apply_admin(request, user_infos): + result, ok = await apply_senior_role(user_infos['user_name'], request.json) + if not ok: + return rsp(code=500, msg=result) + return rsp() + + +@bp.get('/reviewer') +@login_auth +async def get_reviewer_list(_, user_infos): + return rsp(data=await get_reviewers(user_infos['user_name'])) + + +@bp.get('/applicants') +@login_auth +@check_admin +async def get_applicants(request, user_infos): + page_num = int(request.args.get('page_num')) if request.args.get('page_num') else 1 + page_size = int(request.args.get('page_size')) if request.args.get('page_size') else 10 + return rsp(paginate=await get_operator_log(page_num, page_size, False)) + + +@bp.post('/review') +@login_auth +@check_admin +async def review_admin_apply(request, user_infos): + if 'review_list' not in request.json or not request.json.get('review_list'): + return rsp(code=400, msg=ERROR_LACK_ARGS) + if 'review_result' not in request.json: + return rsp(code=400, msg=ERROR_LACK_ARGS) + result, ok = await upgrade_role(user_infos['user_name'], request.json) + if not ok: + return rsp(code=500, msg=result) + return rsp() + + +@bp.get('/review/count') +@login_auth +@check_admin +async def count_review_info(_, user_infos): + return rsp(data=await get_review_count()) + + +@bp.get('/op-record') +@login_auth +@check_admin +async def get_review_record(request, user_infos): + page_num = int(request.args.get('page_num')) if request.args.get('page_num') else 1 + page_size = int(request.args.get('page_size')) if request.args.get('page_size') else 10 + return rsp(paginate=await get_operator_log(page_num, page_size, True)) + + +@bp.post('/update-role') +@login_auth +@check_admin +async def upgrade_role(request, user_infos): + args = ['user_id', 'role', 'method'] + result, ok = check_args(args, request.json) + if not ok: + return result + result, ok = await update_user_role(request.json, user_infos['user_name']) + if not ok: + return rsp(code=500, msg=result) + return rsp() + + +@bp.delete('') +@login_auth +@check_admin +async def delete(request, user_infos): + if 'user_id' not in request.args or not request.args['user_id']: + return rsp(code=400, msg=ERROR_LACK_ARGS) + result, ok = await delete_user(request.args['user_id'], user_infos['user_name']) + if not ok: + return rsp(code=500, msg=result) + return rsp() diff --git a/views/case_view.py b/views/case_view.py new file mode 100644 index 0000000000000000000000000000000000000000..37bb16257dd51905c901aad59c5048119a647996 --- /dev/null +++ b/views/case_view.py @@ -0,0 +1,362 @@ +import os +import time + +from sanic import Blueprint, response + +from common.http import rsp +from services.auth_service import login_auth, read_auth +from services.case_service import * +from views.outline_view import ERROR_OUTLINE_FORMAT +from views.utils import check_args, ERROR_LACK_ARGS + +bp = Blueprint('case', url_prefix='api/case') + + +@bp.route('') +@login_auth +async def get_case_list(request, user_infos): + page_num = int(request.args.get('page_num')) if request.args.get('page_num') else 1 + page_size = int(request.args.get('page_size')) if request.args.get('page_size') else 50 + mod_id = request.args.get('mod_id') + is_recursion = request.args.get('is_recursion') + result = await get_cases(page_num, page_size, mod_id, is_recursion) + return rsp(paginate=result) + + +@bp.get('/search') +@login_auth +async def search(request, user_infos): + page_num = int(request.args.get('page_num')) if request.args.get('page_num') else 1 + page_size = int(request.args.get('page_size')) if request.args.get('page_size') else 50 + result = await search_case(request.args, page_num, page_size) + return rsp(paginate=result) + + +@bp.post('/create') +@read_auth +async def create(request, user_infos): + check_list = ['name', 'suite_name', 'priority', 'run_method', 'run_model', 'is_available'] + res, ok = check_args(check_list, request.json) + if not ok: + return res + if request.json['run_method'] == Case_Run_Method.AUTO.value and 'tone_case' not in request.json: + return rsp(code=400, msg=ERROR_LACK_ARGS) + result, ok = await create_case(request.json, user_infos['user_name']) + if not ok: + return rsp(code=500, msg=result) + return rsp(data=result) + + +@bp.post('/rename/') +@read_auth +async def rename(request, case_id, user_infos): + check_list = ['name'] + res, ok = check_args(check_list, request.json) + if not ok: + return res + result, ok = await rename_case(request.json, user_infos, case_id) + if not ok: + return rsp(code=500, msg=result) + return rsp(data=result) + + +@bp.delete('') +@read_auth +async def delete(request, user_infos): + ids = request.args['id'] + result, ok = await delete_cases(ids, user_infos) + if ok: + return rsp(code=500, msg=result) + return rsp() + + +@bp.post('/move/') +@read_auth +async def move(request, case_id, user_infos): + check_list = ['parent'] + res, ok = check_args(check_list, request.json) + if not ok: + return res + result, ok = await move_case(request.json, case_id) + if not ok: + return rsp(code=500, msg=result) + return rsp(data=result) + + +@bp.post('/move') +@read_auth +async def batch_move(request, user_infos): + check_list = ['parent', 'cases'] + res, ok = check_args(check_list, request.json) + if not ok: + return res + result, ok = await move_cases(request.json) + if not ok: + return rsp(code=500, msg=result) + return rsp() + + +# @bp.post('/import') +async def import_cases(request): + file = request.files.get('excel') + file_type = os.path.splitext(file.name) + + if file_type[1] not in ['.xls', '.xlsx']: + return rsp(code=400, msg=ERROR_OUTLINE_FORMAT) + + await import_excel(file.body) + return rsp() + + +@bp.post('/import/yaml') +@read_auth +async def import_cases_in_yaml_format(request, user_infos): + file = request.files.get('yaml') + file_type = os.path.splitext(file.name) + + if file_type[1] not in ['.yaml']: + return rsp(code=400, msg=ERROR_OUTLINE_FORMAT) + + result, ok = await import_yaml(file.body, file.name) + if not ok: + return rsp(code=500, msg=result) + return rsp() + + +@bp.post('/import/tar') +@read_auth +async def import_cases(request, user_infos): + file = request.files.get('tar') + file_type = os.path.splitext(file.name) + + if file_type[1] not in ['.tar']: + return rsp(code=400, msg=ERROR_OUTLINE_FORMAT) + + result, ok = await import_tar(file.body, file.name) + if not ok: + return rsp(code=500, msg=result) + return rsp() + + +@bp.get('/export') +async def export_cases(request): + file_name = f'{int(time.time())}.xlsx' + if 'case' not in request.args: + file_name = '模板文件.xlsx' + file_body = await excel_template() + else: + file_body = await export_excel(request.args['case']) + content_type = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' + return response.raw( + body=file_body, + status=200, + headers={ + 'Content-Disposition': 'attachment;filename={}'.format(file_name) + }, + content_type=content_type + ) + + +@bp.post('/edit/') +@read_auth +async def edit(request, case_id, user_infos): + check_list = ['run_method', 'run_model', 'is_available'] + res, ok = check_args(check_list, request.json) + if not ok: + return res + if request.json['run_method'] == Case_Run_Method.AUTO.value and 'tone_case' not in request.json: + return rsp(code=400, msg=ERROR_LACK_ARGS) + result, ok = await update_case_content(request.json, user_infos, case_id) + if not ok: + return rsp(code=500, msg=result) + return rsp(data=result) + + +@bp.post('/edit') +@read_auth +async def edit_cases(request, user_infos): + check_list = ['case_ids'] + res, ok = check_args(check_list, request.json) + if not ok: + return res + result, ok = await update_cases(request.json, user_infos) + if not ok: + return rsp(code=500, msg=result) + return rsp() + + +@bp.get('/module/') +@login_auth +async def get_module(request, node_id, user_infos): + key = request.args.get('key') if request.args.get('key') else None + result, ok = await get_follow_modules(node_id, key) + if not ok: + return rsp(code=500, msg=result) + return rsp(data=result) + + +@bp.get('/module/path') +@login_auth +async def get_module(_, user_infos): + return rsp(data=await get_module_path_list()) + + +@bp.get('/module/tree/') +@login_auth +async def get_module(_, node_id, user_infos): + result, ok = await get_follow_module_tree(node_id) + if not ok: + return rsp(code=500, msg=result) + return rsp(data=result) + + +@bp.get('/modules') +@login_auth +async def get_modules(request, user_infos): + start = request.args.get('start') + result = await search_modules(start) + return rsp(data=result) + + +@bp.post('/module/create') +@read_auth +async def create_module(request, user_infos): + check_list = ['name', 'parent'] + res, ok = check_args(check_list, request.json) + if not ok: + return res + result, ok = await create_case_tree_node(request.json) + if not ok: + return rsp(code=500, msg=result) + return rsp(data=result) + + +@bp.post('/module/move/') +@read_auth +async def move_module(request, mod_id, user_infos): + check_list = ['parent'] + res, ok = check_args(check_list, request.json) + if not ok: + return res + result, ok = await update_case_tree_node(request.json, mod_id) + if not ok: + return rsp(code=500, msg=result) + return rsp(data=result) + + +@bp.post('/module/rename/') +@read_auth +async def rename_module(request, mod_id, user_infos): + check_list = ['name'] + res, ok = check_args(check_list, request.json) + if not ok: + return res + result, ok = await rename_case_tree_node(request.json, mod_id) + if not ok: + return rsp(code=500, msg=result) + return rsp(data=result) + + +@bp.delete('/module/') +@read_auth +async def delete_module(_, mod_id, user_infos): + result, ok = await remove_module(mod_id) + if not ok: + return rsp(code=500, msg=result) + return rsp() + + +@bp.post('/suite') +@read_auth +async def create_suite(request, user_infos): + if 'name' not in request.json: + return rsp(code=400, msg=ERROR_LACK_ARGS) + result, ok = await create_test_suite(request.json, user_infos['user_name']) + if not ok: + return rsp(code=500, msg=result) + return rsp(data=result) + + +@bp.get('/suites') +@login_auth +async def get_suite(request, user_infos): + page_num = int(request.args.get('page_num')) if request.args.get('page_num') else 1 + page_size = int(request.args.get('page_size')) if request.args.get('page_size') else 50 + suite_name = request.args.get('name') + is_paginate = request.args.get('is_paginate', '') + result = await get_test_suites(is_paginate != 'false', suite_name, page_num, page_size) + if is_paginate == 'false': + return rsp(data=result) + return rsp(paginate=result) + + +@bp.post('/suite/rename') +@read_auth +async def rename_suite(request, user_infos): + args = ['id', 'name'] + result, ok = check_args(args, request.json) + if not ok: + return result + result, ok = await rename_test_suite(request.json, user_infos) + if not ok: + return rsp(code=500, msg=result) + return rsp(data=result) + + +@bp.delete('/suite') +@read_auth +async def delete_suite(request, user_infos): + if 'id' not in request.args: + return rsp(code=400, msg=ERROR_LACK_ARGS) + result, ok = await remove_test_suite(request.args['id'], user_infos) + if not ok: + return rsp(code=500, msg=result) + return rsp(data=result) + + +@bp.post('/label') +@read_auth +async def create_label(request, user_infos): + if 'name' not in request.json: + return rsp(code=400, msg=ERROR_LACK_ARGS) + result, ok = await create_labels(request.json, user_infos['user_name']) + if not ok: + return rsp(code=500, msg=result) + return rsp(data=result) + + +@bp.get('/labels') +@login_auth +async def get_labels(request, user_infos): + page_num = int(request.args.get('page_num')) if request.args.get('page_num') else 1 + page_size = int(request.args.get('page_size')) if request.args.get('page_size') else 20 + label_name = request.args.get('name', None) + is_paginate = request.args.get('is_paginate', '') + result = await get_label_list(is_paginate != 'false', label_name, page_num, page_size) + if is_paginate == 'false': + return rsp(data=result) + return rsp(paginate=result) + + +@bp.post('/label/rename') +@read_auth +async def rename_label(request, user_infos): + args = ['id', 'name'] + result, ok = check_args(args, request.json) + if not ok: + return result + result, ok = await rename_labels(request.json, user_infos) + if not ok: + return rsp(code=500, msg=result) + return rsp(data=result) + + +@bp.delete('/labels') +@read_auth +async def delete_label(request, user_infos): + if 'id' not in request.args: + return rsp(code=400, msg=ERROR_LACK_ARGS) + result, ok = await remove_labels(request.args['id'], user_infos) + if not ok: + return rsp(code=500, msg=result) + return rsp(data=result) diff --git a/views/common_view.py b/views/common_view.py new file mode 100644 index 0000000000000000000000000000000000000000..d96cf648fb82c25c50d613ae7345d33a783055cd --- /dev/null +++ b/views/common_view.py @@ -0,0 +1,42 @@ +from sanic import Blueprint +from sanic.exceptions import NotFound +from sanic.response import html + +from app.conf import conf +from common.http import rsp, http_request +from services.auth_service import login_auth +from services.common_service import upload_static_file_to_oss + +bp = Blueprint('common', url_prefix='') + + +@bp.get('/config/reload') +async def config_reload(request): + conf.init_app(request.app) + return rsp() + + +@bp.post('/api/oss/image') +@login_auth +async def upload_images(request, user_infos): + file = request.files.get('image') + result = upload_static_file_to_oss(file.name, file.body) + return rsp(data=result) + + +@bp.get('/') +async def index(request): + oss = conf.config['OSS_URL'] + '/' + request.app.name + '/' + conf.config['FRONT_VERSION'] + url = oss + '/index.html' + _, res = await http_request(url, 'get') + res = res.replace('', f'') + return html(res.replace(conf.config['REPLACE_DATA'], oss)) + + +@bp.exception(NotFound) +async def handle_404_redirect(request, exception): + oss = conf.config['OSS_URL'] + '/' + request.app.name + '/' + conf.config['FRONT_VERSION'] + url = oss + '/index.html' + _, res = await http_request(url, 'get') + res = res.replace('', f'') + return html(res.replace(conf.config['REPLACE_DATA'], oss)) diff --git a/views/const.py b/views/const.py new file mode 100644 index 0000000000000000000000000000000000000000..a8cde43ef8681f5029ed160ecb0623df6c0946a8 --- /dev/null +++ b/views/const.py @@ -0,0 +1,13 @@ +from common.http import rsp + +ERROR_LACK_ARGS = '缺少相关参数' +ERROR_EMPTY_ARG = '参数不为空' + + +def check_args(args, request): + for key in args: + if key not in request: + return rsp(code=400, msg=ERROR_LACK_ARGS), False + if not request[key]: + return rsp(code=400, msg=ERROR_EMPTY_ARG), False + return None, True diff --git a/views/device_view.py b/views/device_view.py new file mode 100644 index 0000000000000000000000000000000000000000..7fa490009323627e9d4b66768b9729ecf063bb97 --- /dev/null +++ b/views/device_view.py @@ -0,0 +1,101 @@ +from sanic import Blueprint + +from common.http import rsp +from services.auth_service import login_auth, read_auth +from services.device_service import get_devices, add_device, modify_device, remove_device, get_device_by_id, \ + get_devices_by_type, create_new_label, query_labels, remove_label +from views.utils import check_args + +bp = Blueprint('device', url_prefix='api/device') + + +@bp.route('') +@login_auth +async def get_device_list(request, user_infos): + page_num = int(request.args.get('page_num')) if request.args.get('page_num') else 1 + page_size = int(request.args.get('page_size')) if request.args.get('page_size') else 10 + result = await get_devices(page_num, page_size) + return rsp(paginate=result) + + +@bp.route('/list') +@login_auth +async def get_device_list(request, user_infos): + types = request.args.get('type') + result = await get_devices_by_type(types) + return rsp(data=result) + + +@bp.get('/') +@login_auth +async def get_device(_, device_id, user_infos): + result, ok = await get_device_by_id(device_id) + if not ok: + return rsp(code=400, msg=result) + return rsp(data=result) + + +@bp.post('/add') +@read_auth +async def create(request, user_infos): + checklist = ['name', 'ip', 'arch', 'type'] + response, ok = check_args(checklist, request.json) + if not ok: + return response + result = await add_device(request.json, user_infos['user_name']) + return rsp(data=result) + + +@bp.post('/modify/') +@read_auth +async def modify(request, device_id, user_infos): + checklist = ['name', 'ip', 'arch', 'type'] + response, ok = check_args(checklist, request.json) + if not ok: + return response + result, ok = await modify_device(request.json, device_id, user_infos) + if not ok: + return rsp(code=400, msg=result) + return rsp(data=result) + + +@bp.get('/ping/') +@login_auth +async def ping(_, device_id): + return rsp(data=True) + + +@bp.delete('/') +@read_auth +async def delete_device(_, device_id, user_infos): + result, ok = await remove_device(device_id, user_infos) + if not ok: + return rsp(code=500, msg=result) + return rsp() + + +@bp.post('/label/add') +@read_auth +async def create_label(request, user_infos): + checklist = ['name'] + response, ok = check_args(checklist, request.json) + if not ok: + return response + result = await create_new_label(request.json) + return rsp(data=result) + + +@bp.get('/labels') +@login_auth +async def query_device_label(request, user_infos): + prefix = request.args.get('prefix') if request.args.get('prefix') else None + return rsp(data=await query_labels(prefix)) + + +@bp.delete('/label/') +@read_auth +async def delete_label(_, label_id, user_infos): + result, ok = await remove_label(label_id) + if not ok: + return rsp(code=400, msg=result) + return rsp() diff --git a/views/outline_view.py b/views/outline_view.py new file mode 100644 index 0000000000000000000000000000000000000000..c8f623e020f50a276f22adae59290469024ed580 --- /dev/null +++ b/views/outline_view.py @@ -0,0 +1,118 @@ +import os.path + +from sanic import Blueprint, response + +from common.http import rsp +from services.auth_service import login_auth, read_auth +from services.outline_service import * +from views.utils import ERROR_LACK_ARGS, check_args + +bp = Blueprint('outline', url_prefix='api/outline') + +ERROR_OUTLINE_FORMAT = '上传格式不正确' +ERROR_OUTLINE_UPDATE = '大纲编辑失败' +ERROR_UN_EXIST_OUTLINE = '大纲不存在' + + +@bp.route('') +@login_auth +async def get_outline_list(request, user_infos): + page_num = int(request.args.get('page_num')) if request.args.get('page_num') else 1 + page_size = int(request.args.get('page_size')) if request.args.get('page_size') else 10 + result = await get_outlines(page_num, page_size) + return rsp(paginate=result) + + +@bp.route('/list') +@login_auth +async def get_outline_ids(request, user_infos): + prefix = request.args.get('prefix') if request.args.get('prefix') else '' + result = await query_outlines(prefix) + return rsp(data=result) + + +@bp.post('/upload') +@read_auth +async def upload(request, user_infos): + file = request.files.get('outline') + file_type = os.path.splitext(file.name) + if file_type[1] not in get_outline_format(): + return rsp(code=400, msg=ERROR_OUTLINE_FORMAT) + title = request.form.get('title') + if not title: + return rsp(code=400, msg=ERROR_LACK_ARGS) + remark = request.form.get('remark') if request.form.get('remark') else None + result = await store(file.name, file.body, file_type[1], user_infos['user_name'], title, remark) + return rsp(data=result) + + +@bp.put('/edit/') +@read_auth +async def edit(request, file_id, user_infos): + if not request.form.get('title'): + return rsp(400, ERROR_LACK_ARGS) + file = request.files.get('outline') + if file: + file_type = os.path.splitext(file.name) + if file_type[1] not in get_outline_format(): + return rsp(code=400, msg=ERROR_OUTLINE_FORMAT) + + result, ok = await update(file_id, file, request.form, user_infos) + if not ok: + return rsp(code=500, msg=result) + return rsp() + + +@bp.post('/rename/') +@read_auth +async def rename(request, file_id, user_infos): + args = ['title'] + result, ok = check_args(args, request.json) + if not ok: + return result + result, ok = await modify_title(request.json['title'], file_id, user_infos) + if not ok: + return rsp(code=500, msg=result) + return rsp(data=result) + + +@bp.get('/download/') +@login_auth +async def download(_, file_id, user_infos): + result, ok = await extract(file_id) + if not ok: + return rsp(code=500, msg=result) + content_type = get_content_type(os.path.splitext(result[0])[1]) + headers = { + 'Content-Disposition': f'attachment;filename={result[0]}', + } + return response.raw( + body=result[1], + status=200, + headers=headers, + content_type=content_type + ) + + +@bp.delete('/') +@read_auth +async def delete(_, file_id, user_infos): + result, ok = await remove(file_id, user_infos) + if not ok: + return rsp(code=500, msg=result) + return rsp() + + +def get_outline_format(): + return ['.doc', '.docx', '.txt', '.pdf'] + + +def get_content_type(suffix): + content_type = 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' + if suffix == '.doc': + return 'application/msword' + elif suffix == '.pdf': + return 'application/pdf' + elif suffix == '.txt': + return 'text/plain' + return content_type diff --git a/views/plan_view.py b/views/plan_view.py new file mode 100644 index 0000000000000000000000000000000000000000..45efae43b7517d160e004ec9ce6e461af593a3f1 --- /dev/null +++ b/views/plan_view.py @@ -0,0 +1,115 @@ +from sanic import Blueprint + +from common.http import rsp +from services.auth_service import login_auth, read_auth +from services.plan_service import * +from views.utils import check_args + +bp = Blueprint('plan', url_prefix='api/plan') + + +@bp.route('') +@login_auth +async def get_plan_list(request, user_infos): + page_num = int(request.args.get('page_num')) if request.args.get('page_num') else 1 + page_size = int(request.args.get('page_size')) if request.args.get('page_size') else 30 + content = request.args.get('content') if request.args.get('content') else None + result = await get_plans(content, page_num, page_size) + return rsp(paginate=result) + + +@bp.post('/create') +@read_auth +async def create(request, user_infos): + check_list = ['title', 'req_id', 'reviewers'] + response, ok = check_args(check_list, request.json) + if not ok: + return response + result, ok = await create_plan(request.json, user_infos['user_name']) + if not ok: + return rsp(code=500, msg=result) + return rsp(data=result) + + +@bp.get('/') +@login_auth +async def get_plan(_, plan_id, user_infos): + result, ok = await get_plan_by_id(plan_id) + if not ok: + return rsp(code=500, msg=result) + return rsp(data=result) + + +@bp.post('/edit/') +@read_auth +async def edit(request, plan_id, user_infos): + check_list = ['title', 'content'] + response, ok = check_args(check_list, request.json) + if not ok: + return response + result, ok = await update_plan(request.json, plan_id, user_infos) + if not ok: + return rsp(code=500, msg=result) + return rsp(data=result) + + +@bp.get('//tasks') +@login_auth +async def get_plan_task_list(_, plan_id, user_infos): + result, ok = await get_plan_tasks(plan_id) + if not ok: + return rsp(code=500, msg=result) + return rsp(data=result) + + +@bp.post('/review/') +@read_auth +async def review(request, plan_id, user_infos): + check_list = ['is_accept'] + response, ok = check_args(check_list, request.json) + if not ok: + return response + result, ok = await review_plan(request.json['is_accept'], plan_id, user_infos['user_name']) + if not ok: + return rsp(code=500, msg=result) + return rsp(data=result) + + +@bp.post('/re-review/') +@read_auth +async def re_review(_, plan_id, user_infos): + result, ok = await re_review_plan(plan_id, user_infos['user_name']) + if not ok: + return rsp(code=500, msg=result) + return rsp(data=result) + + +@bp.delete('/') +@read_auth +async def remove(_, plan_id, user_infos): + result, ok = await delete(plan_id, user_infos) + if not ok: + return rsp(code=500, msg=result) + return rsp() + + +@bp.get('//export') +@login_auth +async def export(_, plan_id, user_infos): + return rsp(data=await export_plan(plan_id)) + + +@bp.post('//run') +@login_auth +async def run(_, plan_id, user_infos): + result, ok = await run_task(plan_id, user_infos) + if not ok: + return rsp(code=500, msg=result) + return rsp() + + +@bp.post('//report') +@login_auth +async def check_status(_, plan_id, user_infos): + await generate_plan_report(plan_id) + return rsp() diff --git a/views/requirement_view.py b/views/requirement_view.py new file mode 100644 index 0000000000000000000000000000000000000000..52c26a9b15622cabf93e2021203a21088f1cccee --- /dev/null +++ b/views/requirement_view.py @@ -0,0 +1,83 @@ +from sanic import Blueprint + +from common.http import rsp +from services.auth_service import login_auth, read_auth +from services.requirement_service import get_requirements, update, get_requirement_by_id, delete, review, \ + create_requirement, query_requirements +from views.utils import check_args + +bp = Blueprint('requirement', url_prefix='api/requirement') + + +@bp.route('') +@login_auth +async def get_requirement_list(request, user_infos): + page_num = int(request.args.get('page_num')) if request.args.get('page_num') else 1 + page_size = int(request.args.get('page_size')) if request.args.get('page_size') else 10 + result = await get_requirements(page_num, page_size) + return rsp(paginate=result) + + +@bp.get('/list') +@login_auth +async def query(request, user_infos): + prefix = request.args.get('prefix') if request.args.get('prefix') else '' + result = await query_requirements(user_infos['user_name'], prefix) + return rsp(data=result) + + +@bp.get('/') +@login_auth +async def get_requirement(_, req_id, user_infos): + result, ok = await get_requirement_by_id(req_id, user_infos['user_name']) + if not ok: + return rsp(code=500, msg=result) + return rsp(data=result) + + +@bp.post('/create') +@login_auth +async def create(request, user_infos): + check_keys = ['title', 'assignee'] + response, ok = check_args(check_keys, request.json) + if not ok: + return response + result, ok = await create_requirement(request.json, user_infos['user_name']) + if not ok: + return rsp(code=500, msg=result) + return rsp(data=result) + + +@bp.post('/edit/') +@login_auth +async def edit(request, req_id, user_infos): + check_keys = ['title', 'assignee', 'outline_id'] + response, ok = check_args(check_keys, request.json) + if not ok: + return response + result, ok = await update(req_id, request.json) + if not ok: + return rsp(code=500, msg=result) + return rsp(data=result) + + +@bp.post('/review/') +@read_auth +async def review_requirement(request, req_id, user_infos): + check_keys = ['is_accept'] + response, ok = check_args(check_keys, request.json) + if not ok: + return response + result, ok = await review(req_id, request.json['is_accept'], user_infos['user_name']) + if not ok: + return rsp(code=500, msg=result) + return rsp(data=result) + + +@bp.delete('/') +@login_auth +async def remove(_, req_id, user_infos): + result, ok = await delete(req_id, user_infos) + if not ok: + return rsp(code=500, msg=result) + return rsp() diff --git a/views/task_view.py b/views/task_view.py new file mode 100644 index 0000000000000000000000000000000000000000..9889c11f6313051d1e6fdbf14fb542bc2c077fce --- /dev/null +++ b/views/task_view.py @@ -0,0 +1,87 @@ +from sanic import Blueprint + +from common.enums import Task_Run_Method +from common.http import rsp +from services.auth_service import login_auth, read_auth +from services.task_service import get_tasks, get_task_by_id, create_task, remove_task, found_cases, \ + modify_task, add_run_result +from views.utils import check_args, ERROR_LACK_ARGS + +bp = Blueprint('task', url_prefix='api/task') + + +@bp.route('') +@login_auth +async def get_task_list(request, user_infos): + page_num = int(request.args.get('page_num')) if request.args.get('page_num') else 1 + page_size = int(request.args.get('page_size')) if request.args.get('page_size') else 50 + is_paginate = request.args.get('is_paginate', '') + plan_id = request.args.get('plan_id', None) + name = request.args.get('name', None) + if is_paginate == 'false': + return rsp(data=await get_tasks(name, plan_id, is_paginate, page_num, page_size)) + return rsp(paginate=await get_tasks(name, plan_id, is_paginate, page_num, page_size)) + + +@bp.get('/') +@login_auth +async def get_task(_, task_id, user_infos): + result, ok = await get_task_by_id(task_id) + if not ok: + return rsp(code=500, msg=result) + return rsp(data=result) + + +@bp.post('/create') +@read_auth +async def create(request, user_infos): + args = ['name', 'plan_id', 'cases', 'run_method'] + res, ok = check_args(args, request.json) + if not ok: + return res + if request.json['run_method'] == Task_Run_Method.MANUAL.value and 'config' not in request.json: + return rsp(code=400, msg=ERROR_LACK_ARGS) + result, ok = await create_task(request.json, user_infos['user_name']) + if not ok: + return rsp(code=500, msg=result) + return rsp(data=result) + + +@bp.get('//case') +@login_auth +async def add_case_list(_, task_id, user_infos): + res, ok = await found_cases(task_id) + if not ok: + return rsp(code=500, msg=res) + return rsp(data=res) + + +@bp.post('/update/') +@read_auth +async def update(request, task_id, user_infos): + result, ok = await modify_task(request.json, task_id, user_infos) + if not ok: + return rsp(code=500, msg=result) + return rsp(data=result) + + +@bp.post('//add_result') +@read_auth +async def add_result(request, task_id, user_infos): + args = ['result', 'state'] + res, ok = check_args(args, request.json) + if not ok: + return rsp(code=400, msg=res) + res, ok = await add_run_result(request.json, task_id) + if not ok: + return rsp(code=500, msg=res) + return rsp(data=res) + + +@bp.delete('/') +@read_auth +async def delete(_, task_id, user_infos): + result, ok = await remove_task(task_id, user_infos) + if not ok: + return rsp(code=500, msg=result) + return rsp(data=result) diff --git a/views/tone_view.py b/views/tone_view.py new file mode 100644 index 0000000000000000000000000000000000000000..7e3338103283520717b1fbcc91a83e578d1ae4c6 --- /dev/null +++ b/views/tone_view.py @@ -0,0 +1,50 @@ +from sanic import Blueprint +import asyncio + +from common.http import rsp +from services.auth_service import login_auth, read_auth +from services.tone_service import query_suite, get_tone_case_type, query_tone_cases, sync_suite +from services.tone_job_service import create_tone_job, tone_callback + +bp = Blueprint('tone', url_prefix='api/tone/') + + +@bp.get('/suites') +@login_auth +async def get_tone_case_list(request, user_infos): + page_num = int(request.args.get('page_num')) if request.args.get('page_num') else 1 + result = await query_suite(request.args, page_num, page_size=20) + return rsp(data=result) + + +@bp.get('//cases') +@login_auth +async def get_cases_by_suite_id(request, suite_name, user_infos): + result = await query_tone_cases(request.args, suite_name) + return rsp(data=result) + + +@bp.get('/test-type') +@login_auth +async def get_test_type(_, user_infos): + result = await get_tone_case_type() + return rsp(data=result) + + +@bp.post('/create_job') +@read_auth +async def create_job_view(request, user_infos): + result = await create_tone_job(request.json) + return rsp(data=result) + + +# todo: 对tone的认证 +@bp.post('/callback') +async def tone_callback_view(request): + result = await tone_callback(request.json) + return rsp(data=result) + + +@bp.listener('after_server_start') +async def sync_data(bp, loop): + asyncio.create_task(sync_suite()) diff --git a/views/utils.py b/views/utils.py new file mode 100644 index 0000000000000000000000000000000000000000..173b5273e4d3ab5699075771bcd94ee54e806608 --- /dev/null +++ b/views/utils.py @@ -0,0 +1,14 @@ +from common.http import rsp + +ERROR_LACK_ARGS = '缺少相关参数' +ERROR_EMPTY_ARG = '参数不为空' +ERROR_FAILED_DELETE = '删除失败' + + +def check_args(args, request): + for key in args: + if key not in request: + return rsp(code=400, msg=ERROR_LACK_ARGS), False + if not request[key] and request[key] != 0: + return rsp(code=400, msg=ERROR_EMPTY_ARG), False + return None, True