def plan_worktable_snap_plugin_delete(): # 初始化返回内容 response_json = {"code": 200, "msg": "操作成功", "data": {}} # 取出 mail = flask.request.headers['Mail'] plan_id = int(flask.request.args['plan_id']) pid = int(flask.request.args['pid']) result, msg = check_plan_owner(mail, plan_id) if result is None or result is False: return msg resource_path = appconfig.get("task", "filePutDir") resource_path = resource_path[:-1] if resource_path[ -1] == "/" else resource_path resource_path = "%s/%s/%s" % (resource_path, plan_id, pid) if os.path.exists(resource_path) and os.path.isdir(resource_path): try: shutil.rmtree(resource_path) except Exception as e: api_logger.error("文件删除失败,失败原因:" + repr(e)) return route.error_msgs[500]['msg_file_error'] # 最后返回内容 return response_json
def set_snap_table_data(plan_id, table): # 从缓存中获取时间 cache_time_bytes = modle_redis_apitestplanworktable.query_time( plan_id=plan_id) # 如果时间获取成功,则比较当前时间和缓存的时间 if cache_time_bytes is not None: cache_time = datetime.datetime.strptime( cache_time_bytes.decode("utf8"), "%Y-%m-%d %H:%M:%S") # 如果没有超出15分钟(可配置),则仅刷新redis中内容 if (datetime.datetime.now() - cache_time).seconds <= int( appconfig.get("task", "snapSyncInterval")): modle_redis_apitestplanworktable.set_table(plan_id, table) return True # 如果超出了15分钟(可配置),则先刷新redis中内容与时间,再同步至mysql生成快照,且更新时间 else: redis_set_flag = True redis_set_flag = modle_redis_apitestplanworktable.set_table( plan_id, table) redis_set_flag = modle_redis_apitestplanworktable.set_time(plan_id) if redis_set_flag: # mysql中新增snap # 将status为1的snap全部置为失效 try: model_mysql_tablesnap.query.filter( and_(model_mysql_tablesnap.planId == plan_id, model_mysql_tablesnap.status == 1)).update( {"status": 0}) mysqlpool.session.commit() except Exception as e: api_logger.error("model_mysql_tablesnap数据更新失败,失败原因:" + repr(e)) return False else: # 新增status为1的snap,内容即为接口传参内容 new_snap = model_mysql_tablesnap( status=1, planId=plan_id, snapAddTime=datetime.datetime.now(), table=table) try: mysqlpool.session.add(new_snap) mysqlpool.session.commit() except Exception as e: api_logger.error("new_snap数据写入失败,失败原因:" + repr(e)) return False else: return True else: return False # 如果时间获取失败,则直接将内容写入redis else: redis_set_flag = True redis_set_flag = modle_redis_apitestplanworktable.set_table( plan_id, table) redis_set_flag = modle_redis_apitestplanworktable.set_time(plan_id) return redis_set_flag
def plan_worktable_snap_plugin_file_post(): # 初始化返回内容 response_json = { "code": 200, "msg": "操作成功", "data": { "name": "", "uuid": "" } } # 取出 mail = flask.request.headers['Mail'] plan_id = flask.request.form['plan_id'] pid = flask.request.form['id'] result, msg = check_plan_owner(mail, plan_id) if result is None or result is False: return msg # 得到uuid转换后的文件名 request_file = flask.request.files['file'] response_json['data']['name'] = request_file.filename response_json['data']['uuid'] = "%s.%s" % ( uuid.uuid1().hex, request_file.filename.split('.')[-1]) # 将文件存储至指定路径下 # 按照:指定路径/plan_id/id下 resource_path = appconfig.get("task", "filePutDir") resource_path = resource_path[:-1] if resource_path[ -1] == "/" else resource_path resource_path = "%s/%s/%s" % (resource_path, plan_id, pid) # 根据配置文件中的路径,判断账户私有文件夹是否存在 if os.path.exists(resource_path) is False or os.path.isdir( resource_path) is False: # 新建文件夹 try: os.makedirs(resource_path) except Exception as e: api_logger.error("文件夹创建失败,失败原因:" + repr(e)) return route.error_msgs[500]['msg_file_error'] # 将文件保存至指定路径 try: request_file.save("%s/%s" % (resource_path, response_json['data']['uuid'])) except Exception as e: api_logger.error("文件保存失败,失败原因:" + repr(e)) return route.error_msgs[500]['msg_file_error'] # 最后返回内容 return response_json
def plan_worktable_snap_plugin_post(): # 初始化返回内容 response_json = { "code": 200, "msg": "操作成功", "data": {} } # 如果传了文件uuid名称,则删除对应的;如果没传,则删除所有 result, msg = check_plan_owner(flask.request.headers['Mail'], flask.request.json['plan_id']) if result is None or result is False: return msg # 尝试将a文件夹拷贝成b文件夹 # 按照:指定路径/plan_id/id下 resource_path = appconfig.get("task", "filePutDir") resource_path = resource_path[:-1] if resource_path[-1] == "/" else resource_path resource_path_a = "%s/%s/%s" % ( resource_path, flask.request.json['plan_id'], flask.request.json['a_id'] ) resource_path_b = "%s/%s/%s" % ( resource_path, flask.request.json['plan_id'], flask.request.json['b_id'] ) # 如果b文件夹存在,则删除 if os.path.exists(resource_path_b) and os.path.isdir(resource_path_b): # 删除文件夹 try: shutil.rmtree(resource_path_b) except Exception as e: api_logger.error("文件夹删除失败,失败原因:" + repr(e)) return route.error_msgs[500]['msg_file_error'] if os.path.exists(resource_path_a) and os.path.isdir(resource_path_a): # 新建文件夹 try: shutil.copytree(resource_path_a, resource_path_b) except Exception as e: api_logger.error("文件夹复制失败,失败原因:" + repr(e)) return route.error_msgs[500]['msg_file_error'] # 最后返回内容 return response_json
def plan_worktable_snap_plugin_file_get(): # 初始化返回内容 response_json = { "code": 200, "msg": "操作成功", "data": {} } # 取出 mail = flask.request.headers['Mail'] plan_id = int(flask.request.args['plan_id']) pid = int(flask.request.args['id']) uuid = flask.request.args['uuid'] result, msg = check_plan_owner(mail, plan_id) if result is None or result is False: return msg resource_path = appconfig.get("task", "filePutDir") resource_path = resource_path[:-1] if resource_path[-1] == "/" else resource_path resource_path = "%s/%s/%s/%s" % ( resource_path, plan_id, pid, uuid ) if os.path.exists(resource_path) and os.path.isfile(resource_path): # memory_file = io.BytesIO() # zf = zipfile.ZipFile(memory_file, "a", zipfile.ZIP_DEFLATED) # zf.write(resource_path, flask.request.args['uuid']) # zf.close() # memory_file.seek(0, 0) # mimetypes.guess_type(resource_path)[0], # chardet.detect(memory_file.read())['encoding'].replace('-', '').lower() return flask.send_file( resource_path, mimetype=mimetypes.guess_type(resource_path)[0], attachment_filename='%s.zip' % uuid, as_attachment=True ) # 最后返回内容 return response_json
# -*- coding: utf-8 -*- from automation import automation from handler.log import sys_logger from handler.config import appconfig from gevent import pywsgi from geventwebsocket.handler import WebSocketHandler if __name__ == '__main__': logmsg = "系统初始化|准备启动测试环境" sys_logger.info(logmsg) try: # 不能在生产环境中执行本文件 # automation.run(debug=False, host=appconfig.get("api", "host"), port=int(appconfig.get("api", "port"))) server = pywsgi.WSGIServer( (appconfig.get("api", "host"), int(appconfig.get("api", "port"))), automation, handler_class=WebSocketHandler ) print('服务已启动') server.serve_forever() except Exception as e: logmsg = "系统初始化|测试环境启动失败,失败原因:" + repr(e) sys_logger.error(logmsg) logmsg = "系统初始化|测试环境启动结束" sys_logger.info(logmsg)
def task_post(): # 初始化返回内容 response_json = {"code": 200, "msg": "操作成功", "data": {}} # 取出数据 # header user_id = flask.request.headers['UserId'] # body plan_id = flask.request.json['planId'] description = flask.request.json['description'] start_type = flask.request.json['startType'] run_type = flask.request.json['runType'] # 如果startType为2则需要检查执行时间 datetime_start_time = None datetime_end_time = None if start_type == 2: # 开始时间检查 if 'startTime' not in flask.request.json: api_logger.debug("传参缺少startTime") return route.error_msgs[302]['msg_request_params_incomplete'] elif type(flask.request.json['startTime']) is not int: api_logger.debug("传参startTime类型错误") return route.error_msgs[301]['msg_value_type_error'] elif flask.request.json['startTime'] < int(time.time()): api_logger.debug("传参startTime大小错误") return route.error_msgs[201]['msg_too_early'] # 结束时间检查 if 'endTime' not in flask.request.json: api_logger.debug("传参缺少endTime") return route.error_msgs[302]['msg_request_params_incomplete'] elif type(flask.request.json['endTime']) is not int: api_logger.debug("传参endTime类型错误") return route.error_msgs[301]['msg_value_type_error'] elif flask.request.json[ 'endTime'] < flask.request.json['startTime'] + 10: api_logger.debug("传参endTime大小错误") return route.error_msgs[201]['msg_task_time_error'] try: datetime_start_time = time.strftime( "%Y-%m-%d %H:%M:%S", time.localtime(flask.request.json['startTime'])) datetime_end_time = time.strftime( "%Y-%m-%d %H:%M:%S", time.localtime(flask.request.json['endTime'])) except: return route.error_msgs[201]['msg_data_error'] # 如果runType为1则需要检查执行次数 times = None if run_type == 1: print(1111111) if 'times' not in flask.request.json: return route.error_msgs[302]['msg_request_params_incomplete'] elif type(flask.request.json['times']) is not int: return route.error_msgs[301]['msg_value_type_error'] elif flask.request.json['times'] < 1: return route.error_msgs[201]['msg_data_error'] times = flask.request.json['times'] # 为了将来能够看日志,必须要有不变的快照数据,所以tableSnap的不靠谱 # 尝试于redis读取工作台快照临时数据 # 如果有,以这些内容发起测试任务 # 如果无,则读取mysql中最新的内容,发起测试任务 tablesnap_data = None redis_get_table_bytes = modle_redis_apitestplanworktable.query_table( plan_id) if redis_get_table_bytes is not None: tablesnap_data = redis_get_table_bytes.decode('utf-8') else: # 根据planId去查询工作台快照内容 try: mysql_tablesnap = model_mysql_tablesnap.query.filter( and_(model_mysql_tablesnap.planId == plan_id, model_mysql_tablesnap.status == 1)).first() api_logger.debug("接口测试计划工作台快照内容查找成功") except Exception as e: api_logger.debug("接口测试计划工作台快照内容查找失败,失败原因:" + repr(e)) return route.error_msgs[500]['msg_db_error'] else: # 如果查询出来存在记录并且为正式版本,则继续,否则返回错误信息 # 需排除数据异常 if not mysql_tablesnap: return route.error_msgs[201]['msg_no_data'] else: tablesnap_data = mysql_tablesnap.table # 新增测试任务创建记录 # 1.准备测试任务基础数据 new_task_info = model_mysql_taskinfo( planId=plan_id, snap=tablesnap_data, taskType=1, startType=start_type, endType=run_type, taskDescription=description, createTime=datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"), createUser=user_id) # 剩余未填写项目 startTime/endTime/excuteTimes/if_error/vUser/rampUpPeriod # startTime/endTime if start_type == 1: new_task_info.startTime = datetime.datetime.now().strftime( "%Y-%m-%d %H:%M:%S") elif start_type == 2: new_task_info.startTime = datetime_start_time new_task_info.endTime = datetime_end_time # excuteTimes if run_type == 1: new_task_info.excuteTimes = times # if_error # 暂时不支持自定义 new_task_info.errorType = 1 # rampUpPeriod # 暂时不支持自定义 new_task_info.rampUpPeriod = 0 # vUser if 'userNum' in flask.request.json: normal_v_user = flask.request.json['userNum'] if type(normal_v_user) is int and normal_v_user in range(1, 1001): new_task_info.vUser = normal_v_user else: return route.error_msgs[301]['msg_value_type_error'] else: return route.error_msgs[302]['msg_request_params_incomplete'] # 新增测试任务记录 try: mysqlpool.session.add(new_task_info) mysqlpool.session.commit() except Exception as e: api_logger.error("新增测试任务失败,原因:" + repr(e)) return route.error_msgs[500]['msg_db_error'] else: api_logger.debug("新增测试任务成功") # 准备待发送的测试任务文件 # 将工作台内容保存为task.json文件 # 封装测试任务数据 # 检查文件存放路径 if not os.path.exists('file/'): api_logger.debug('存放测试任务文件的file主目录不存在,尝试创建...') try: os.makedirs('file/') except Exception as e: api_logger.error('存放测试任务文件的file目录创建失败,原因:' + repr(e)) return route.error_msgs[500]['msg_file_error'] else: api_logger.debug('存放测试任务文件的file目录创建成功') the_now = datetime.datetime.now() the_year = str(the_now.year) the_month = str(the_now.month) the_day = str(the_now.day) if not os.path.exists('file/' + the_year): api_logger.debug('年份目录不存在,尝试创建...') try: os.makedirs('file/' + the_year) except Exception as e: api_logger.error('年份目录创建失败,原因:' + repr(e)) return route.error_msgs[500]['msg_file_error'] else: api_logger.debug('年份目录创建成功') if not os.path.exists('file/' + the_year + '/' + the_month): api_logger.debug('月份目录不存在,尝试创建...') try: os.makedirs('file/' + the_year + '/' + the_month) except Exception as e: api_logger.error('月份目录创建失败,原因:' + repr(e)) return route.error_msgs[500]['msg_file_error'] else: api_logger.debug('月份目录创建成功') if not os.path.exists('file/' + the_year + '/' + the_month + '/' + the_day): api_logger.debug('日子目录不存在,尝试创建...') try: os.makedirs('file/' + the_year + '/' + the_month + '/' + the_day) except Exception as e: api_logger.error('日子目录创建失败,原因:' + repr(e)) return route.error_msgs[500]['msg_file_error'] else: api_logger.debug('日子目录创建成功') dir_path = 'file/' + the_year + '/' + the_month + '/' + the_day task_dir_path = dir_path + '/task_%s_%s' % (str( new_task_info.taskId), the_now.strftime('%Y%m%d%H%M%S')) api_logger.debug('尝试创建测试任务目标目录...') try: # 于file目录下创建 年/月/日/task_taskId_时间戳 文件夹 os.makedirs(task_dir_path) # 将项目文件夹(其中为参数化文件)复制到task文件夹下 resource_path = appconfig.get("task", "filePutDir") resource_path = resource_path[:-1] if resource_path[ -1] == "/" else resource_path resource_path = "%s/%s" % (resource_path, plan_id) # 根据配置文件中的路径,判断测试计划文件夹是否存在 if os.path.exists(resource_path) is False or os.path.isdir( resource_path) is False: os.makedirs(task_dir_path + '/files') else: shutil.copytree(resource_path, task_dir_path + '/files') except Exception as e: api_logger.error('测试任务目标目录创建失败,原因:' + repr(e)) return route.error_msgs[500]['msg_file_error'] else: api_logger.debug('测试任务目标目录创建成功') # 将测试任务数据存为json文件 file = open(task_dir_path + '/task.json', 'w', encoding='utf-8') file.write(tablesnap_data) file.close() # 将文件夹整个进行zip压缩 z = zipfile.ZipFile(task_dir_path + '.zip', 'w', zipfile.ZIP_DEFLATED) # 将task.json/file添加入压缩包 z.write(os.path.join(task_dir_path, 'task.json'), 'task.json') z.write(os.path.join(task_dir_path, 'files'), 'files') # 将file文件夹下所有文件添加入压缩包 for dir_path, dir_names, file_names in os.walk( os.path.join(task_dir_path, 'files')): for fn in file_names: if fn not in z.NameToInfo: z.write(os.path.join(dir_path, fn), os.path.join('files', fn)) z.close() # 查询计划类型 try: mysql_planinfo = model_mysql_planinfo.query.filter( model_mysql_planinfo.planId == plan_id).first() except Exception as e: api_logger.debug("model_mysql_planinfo数据读取失败,失败原因:" + repr(e)) return route.error_msgs[500]['msg_db_error'] else: # 根据计划类型下发测试任务 if mysql_planinfo.planType == 1: deploy_result, deploy_msg = single_deploy(base=new_task_info, file=task_dir_path + '.zip') if not deploy_result: print(7777) response_json['code'] = 500 response_json[ 'error_msg'] = '测试任务下发失败,原因:%s,请联系管理员或稍后再发起测试任务' % deploy_msg return json.dumps(response_json) return response_json
def user_password_reset_apply_post(): # 初始化返回内容 response_json = {"code": 200, "msg": "", "data": {}} # 取出传入参数值 requestvalue_mail = flask.request.json["mail_address"] # 校验邮箱地址格式 mail_reg = '^([a-zA-Z0-9]+[_|\_|\.]?)*[a-zA-Z0-9]+@([a-zA-Z0-9]+[_|\_|\.]?)*[a-zA-Z0-9]+\.[a-zA-Z]{2,3}$' if not re.search(mail_reg, requestvalue_mail): return route.error_msgs[201]['msg_illegal_format'] # 2.校验账户是否存在 try: uinfo_mysql = model_mysql_userinfo.query.filter( or_(model_mysql_userinfo.userEmail == requestvalue_mail, model_mysql_userinfo.userNewEmail == requestvalue_mail)).first() except Exception as e: logmsg = "数据库中账户信息读取失败,失败原因:" + repr(e) api_logger.error(logmsg) return route.error_msgs[500]['msg_db_error'] else: if uinfo_mysql is None: return route.error_msgs[201]['msg_no_user'] elif uinfo_mysql.userStatus == 1: pass elif uinfo_mysql.userStatus == 0: return route.error_msgs[201]['msg_need_register'] elif uinfo_mysql.userStatus == -1: return route.error_msgs[201]['msg_user_forbidden'] else: return route.error_msgs[201]['msg_status_error'] # 检查通过 # 查询关键操作唯一标识符 odata = ApiCheck.check_operate(appconfig.get("operation_alias", "register")) if odata["exist"] is True: pass elif odata["exist"] is False: return ApiError.requestfail_error("关键操作别名不存在") else: return ApiError.requestfail_server("操作处理异常") # 查库,将之前未进行重置密码操作的记录全部置为无效 try: data = model_mysql_useroperationrecord.query.filter_by( userId=uinfo_mysql.userId, operationId=odata["operationId"], recordStatus=0).all() except Exception as e: logmsg = "mysql中账户操作数据查询失败,失败原因:" + repr(e) api_logger.error(logmsg) return route.error_msgs[500]['msg_db_error'] for d in data: d.recordStatus = -1 try: mysqlpool.session.commit() except Exception as e: logmsg = "mysql中账户操作数据更新失败,失败原因:" + repr(e) api_logger.error(logmsg) return route.error_msgs[500]['msg_db_error'] # 生成操作码 code = str( uuid.uuid3( uuid.NAMESPACE_DNS, requestvalue_mail + str(datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')))) # 将内容入库 insertdata = model_mysql_useroperationrecord( userId=uinfo_mysql.userId, operationId=odata["operationId"], recordCode=code, recordStatus=0, recordValidTime=( datetime.datetime.now() + datetime.timedelta(days=1)).strftime('%Y-%m-%d %H:%M:%S')) try: mysqlpool.session.add(insertdata) mysqlpool.session.commit() except Exception as e: logmsg = "mysql中账户操作数据新增失败,失败原因:" + repr(e) api_logger.error(logmsg) return route.error_msgs[500]['msg_db_error'] # 发送重置密码邮件 publicmailer.sendmail_reset_password(uinfo_mysql.userId, requestvalue_mail, code, odata["operationId"]) # 定义msg response_json["msg"] = "操作成功,请查收重置密码邮件" # 最后返回内容 return response_json
def sendmail_changemail_success(self, to): # 检查传参合法性 # to if type(to) is str: logmsg = "准备给" + to + "发送账户绑定邮箱修改成功邮件" sys_logger.info(logmsg) # 编辑邮件具体内容 mail_msg = """ <html> <head> <style type="text/css"> #platform_logo { height: 18px; } #platform_logo_left{ transition: all 0.5s; fill: #4DB6FF; } #platform_logo_center{ transition: all 0.5s; fill: #539D2C; } #platform_logo_right{ transition: all 0.5s; fill: #EDA833; } #platform_logo > path:hover{ transition: all 0.5s; fill: lightgrey; } </style> </head> <body style="margin:0;"> <div style="background-color: #f5f5f5;"> <div style="margin-left: 20px;padding-top: 10px; padding-bottom: 10px;font-size: 18px;font-weight: 600;"> Dear %s, </div> <div style="position: relative;margin-left: 20px;margin-right: 20px; font-size: 15px;background-color: white;border: 1px solid darkgrey;border-radius: 4px;"> <div style="margin-top: 15px;margin-left: 15px;padding-bottom: 10px;"> 您正在尝试修改绑定邮箱: <a href="%s">绑定邮箱修改成功</a> <div style="margin-left: 10px;padding-bottom: 10px;font-size: 16px;"></div> </div> </div> <div style="margin-top: 10px;padding-bottom: 10px; color: darkgrey;text-align: right;"> <div style="margin-right: 20px;font-size: 12px;"> 本条消息发送自%s测试平台 </div> </div> </div> </body> </html> """ % ( to.split("@")[0], appconfig.get("web", "http") + "://" + appconfig.get("web", "host") + ":" + appconfig.get("web", "port") + appconfig.get("web_url", "login"), appconfig.get('org', 'abbreviation'), ) # 装载消息 # 添加根MIME msg = MIMEText(mail_msg, 'html', 'utf-8') # 初始化邮件发送人 msg['From'] = Header(self.send_address, 'utf-8') # 初始化邮件接收人 msg['To'] = Header(to, 'utf-8') # 初始化邮件主题 msg['Subject'] = Header( '%s测试平台-账号注册' % appconfig.get('org', 'abbreviation'), 'utf-8' ) # 发送 result_flag, result_type = self.__send(to, msg) logmsg = "给" + to + "发送绑定邮箱修改成功邮件结束" sys_logger.info(logmsg) return result_flag, result_type else: logmsg = "接收邮件地址或校验码填写非法" sys_logger.error(logmsg) return False, -1
def sendmail_reset_password(self, user_id, to, code, operationid): # 检查传参合法性 # to if type(to) is str and type(code) is str: logmsg = "准备给" + to + "发送重置密码邮件" sys_logger.info(logmsg) # 编辑邮件具体内容 mail_msg = """ <html> <head> <style type="text/css"> #platform_logo { height: 18px; } #platform_logo_left{ transition: all 0.5s; fill: #4DB6FF; } #platform_logo_center{ transition: all 0.5s; fill: #539D2C; } #platform_logo_right{ transition: all 0.5s; fill: #EDA833; } #platform_logo > path:hover{ transition: all 0.5s; fill: lightgrey; } </style> </head> <body style="margin:0;"> <div style="background-color: #f5f5f5;"> <div style="margin-left: 20px;padding-top: 10px; padding-bottom: 10px;font-size: 18px;font-weight: 600;"> Dear %s, </div> <div style="position: relative;margin-left: 20px;margin-right: 20px; font-size: 15px;background-color: white;border: 1px solid darkgrey;border-radius: 4px;"> <div style="margin-top: 15px;margin-left: 15px;padding-bottom: 10px;"> 您正在尝试重置密码: <a href="%s?userId=%s&mail=%s&code=%s&operate=%s">点我打开重置密码页</a> <div style="margin-left: 10px;padding-bottom: 10px;font-size: 16px;"></div> </div> </div> <div style="margin-top: 10px;padding-bottom: 10px; color: darkgrey;text-align: right;"> <div style="margin-right: 20px;font-size: 12px;"> 本条消息发送自%s测试平台 </div> </div> </div> </body> </html> """ % ( to.split("@")[0], appconfig.get("web", "http") + "://" + appconfig.get("web", "host") + ":" + appconfig.get("web", "port") + appconfig.get("web_url", "resetPassword"), str(user_id), parse.quote(to), parse.quote(code), str(operationid), appconfig.get('org', 'abbreviation'), ) # 装载消息 # 添加根MIME msg = MIMEText(mail_msg, 'html', 'utf-8') # 初始化邮件发送人 msg['From'] = Header(self.send_address, 'utf-8') # 初始化邮件接收人 msg['To'] = Header(to, 'utf-8') # 初始化邮件主题 msg['Subject'] = Header( '%s测试平台-账号注册' % appconfig.get('org', 'abbreviation'), 'utf-8' ) # 发送 self.__send(to, msg) logmsg = "给" + to + "发送重置密码邮件结束" sys_logger.info(logmsg) return True else: logmsg = "接收邮件地址或校验码填写非法" sys_logger.error(logmsg) return False
def user_info_put(): # 初始化返回内容 response_json = {"code": 200, "msg": "", "data": {}} # 取出参数 rq_file_url = flask.request.json['fileUrl'] rq_user_id = flask.request.json['userId'] rq_new_mail_address = flask.request.json['newMailAddress'] rq_nick_name = flask.request.json['nickName'] rq_introduce = flask.request.json['introduceContent'] # 校验传参 # new_mail_address mail_reg = '^([a-zA-Z0-9]+[_|\_|\.]?)*[a-zA-Z0-9]+@([a-zA-Z0-9]+[_|\_|\.]?)*[a-zA-Z0-9]+\.[a-zA-Z]{2,3}$' if not re.search(mail_reg, rq_new_mail_address): return route.error_msgs[301]['msg_value_type_error'] # 如果邮箱变更了,则需要检查新邮箱是否已被注册 # 在库中获取账户信息,准备修改新邮箱信息 try: user_info = model_mysql_userinfo.query.filter_by( userId=rq_user_id).first() except Exception as e: api_logger.error("数据库账户数据查询失败,失败原因:" + repr(e)) return route.error_msgs[500]['msg_db_error'] else: # 校验账户状态 # 仅状态正常的账户支持信息修改 if user_info is None: return route.error_msgs[201]['msg_no_user'] elif user_info.userStatus == 1: pass elif user_info.userStatus == 0: return route.error_msgs[201]['msg_need_register'] elif user_info.userStatus == -1: return route.error_msgs[201]['msg_user_forbidden'] else: return route.error_msgs[500]['msg_server_error'] # 检查传递邮箱 # 如果已被注册则返回错误信息 # 如果未被注册则将新邮箱地址入库并发送确认邮件 if user_info.userEmail != rq_new_mail_address: # 校验新账户是否存在,排除存在的场景 try: newuserdata = model_mysql_userinfo.query.filter_by( userEmail=rq_new_mail_address).first() except Exception as e: api_logger.error("数据库账户数据查询失败,失败原因:" + repr(e)) return route.error_msgs[500]['msg_db_error'] else: if newuserdata is not None: return route.error_msgs[201]['msg_mail_exist'] # 生成操作码,尝试发送修改邮箱确认邮件 # 如果邮件发送成功,则在账号表中新增/覆盖userNewEmail字段内容 # 查询关键操作唯一标识符 odata = ApiCheck.check_operate( appconfig.get("operation_alias", "changeMail")) if odata["exist"] is True: pass elif odata["exist"] is False: return route.error_msgs[201]['msg_operation_alias_not_exist'] else: return route.error_msgs[500]['msg_server_error'] # 生成操作码 code = str( uuid.uuid3( uuid.NAMESPACE_DNS, rq_new_mail_address + str(datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')))) # 发送包含账户信息确认页链接的邮件 # 先发送邮件,成功后再记录数据 # 保证过滤掉不存在的邮件地址 send_result_flag, send_result_type = publicmailer.sendmail_change_mail( rq_user_id, user_info.userEmail, rq_new_mail_address, code, 3) # 如果发送失败,则返回错误信息 if send_result_flag is False: if send_result_type == -1: return route.error_msgs[500]['msg_smtp_error'] elif send_result_type == 1 or send_result_type == 2: return route.error_msgs[500]['msg_public_mail_login_fail'] elif send_result_type == 3: return route.error_msgs[201]['msg_mail_send_fail'] else: # 修改操作记录,将之前的修改绑定邮箱的操作记录置为-1 try: rdata_mysql = model_mysql_useroperationrecord.query.filter_by( userId=user_info.userId, operationId=odata["operationId"], recordStatus=0).all() except Exception as e: api_logger.error("账户操作记录数据查询失败,失败原因:" + repr(e)) return route.error_msgs[500]['msg_db_error'] # 如果查询到了,则全部置为无效 if rdata_mysql is not None: for d in rdata_mysql: d.recordStatus = -1 try: mysqlpool.session.commit() except Exception as e: api_logger.error("账户操作记录数据更新失败,失败原因:" + repr(e)) return route.error_msgs[500]['msg_db_error'] # 将新的操作码数据写入mysql insertdata = model_mysql_useroperationrecord( userId=user_info.userId, operationId=odata["operationId"], recordCode=code, recordStatus=0, recordValidTime=( datetime.datetime.now() + datetime.timedelta(days=1)).strftime('%Y-%m-%d %H:%M:%S')) try: mysqlpool.session.add(insertdata) mysqlpool.session.commit() except Exception as e: logmsg = "数据库新增申请修改绑定邮箱记录数据失败,失败原因:" + repr(e) api_logger.error(logmsg) return route.error_msgs[500]['msg_db_error'] # 修改其新邮件地址信息 user_info.userNewEmail = rq_new_mail_address # 变更邮箱需要变更返回信息 response_json["msg"] = "基础信息修改成功,请于新邮箱查收修改绑定邮箱确认邮件" else: # 返回普通成功信息 response_json["msg"] = "基础信息修改成功" # 修改头像地址/昵称/简介 user_info.userHeadIconUrl = rq_file_url user_info.userNickName = rq_nick_name user_info.userIntroduction = rq_introduce # 尝试写入mysql try: mysqlpool.session.commit() except Exception as e: api_logger.error("账户信息存入数据库失败,失败原因:" + repr(e)) return route.error_msgs[500]['msg_db_error'] # 最后返回内容 return response_json
def new_user_info_post(): # 初始化返回内容 response_json = {"code": 200, "msg": "", "data": {}} # 取出传入参数值 requestvalue_mail = flask.request.json["mail_address"] # 校验邮箱地址格式 mail_reg = '^([a-zA-Z0-9]+[_|\_|\.]?)*[a-zA-Z0-9]+@([a-zA-Z0-9]+[_|\_|\.]?)*[a-zA-Z0-9]+\.[a-zA-Z]{2,3}$' if not re.search(mail_reg, requestvalue_mail): return route.error_msgs[201]['msg_illegal_format'] # 2.校验账户是否存在 try: uinfo_mysql = model_mysql_userinfo.query.filter( or_(model_mysql_userinfo.userEmail == requestvalue_mail, model_mysql_userinfo.userNewEmail == requestvalue_mail)).first() except Exception as e: logmsg = "数据库中账户信息读取失败,失败原因:" + repr(e) api_logger.error(logmsg) return route.error_msgs[500]['msg_db_error'] else: if uinfo_mysql is None: pass elif uinfo_mysql.userStatus == 0: pass elif uinfo_mysql.userStatus in [-2, -1, 1]: return route.error_msgs[201]['msg_mail_exist'] else: return route.error_msgs[201]['msg_status_error'] # 3.如果账户不存在,则数据库以及缓存中插入未激活状态的账户数据以及对应的未完成的操作记录 if uinfo_mysql is None: # 查询关键操作唯一标识符 odata = ApiCheck.check_operate( appconfig.get("operation_alias", "register")) if odata["exist"] is True: pass elif odata["exist"] is False: return route.error_msgs[500]['msg_server_error'] else: return route.error_msgs[500]['msg_server_error'] # 在库中插入账户未激活的信息 # 先插入mysql newuser = model_mysql_userinfo(userEmail=requestvalue_mail, userStatus=0, userAddTime=datetime.datetime.now()) try: mysqlpool.session.add(newuser) mysqlpool.session.commit() except Exception as e: logmsg = "数据库新增账户数据失败,失败原因:" + repr(e) api_logger.error(logmsg) return ApiError.requestfail_server(logmsg) # 生成操作码 code = str( uuid.uuid3( uuid.NAMESPACE_DNS, requestvalue_mail + str(datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')))) # 发送包含账户信息确认页链接的邮件 # 先发送邮件,成功后再记录数据 # 保证过滤掉不存在的邮件地址 send_result_flag, send_result_type = publicmailer.sendmail_register( newuser.userId, requestvalue_mail, code, odata["operationId"]) print(odata["operationId"]) # 如果发送失败,则返回错误信息 if send_result_flag is False: if send_result_type == -1: return ApiError.requestfail_server("SMTP服务器连接失败") elif send_result_type == 1 or send_result_type == 2: return ApiError.requestfail_server("公共邮箱登陆失败") elif send_result_type == 3: return ApiError.requestfail_error("邮件发送失败,请检查邮箱地址") # 将操作码数据写入mysql insertdata = model_mysql_useroperationrecord( userId=newuser.userId, operationId=odata["operationId"], recordCode=code, recordStatus=0, recordValidTime=( datetime.datetime.now() + datetime.timedelta(days=1)).strftime('%Y-%m-%d %H:%M:%S')) try: mysqlpool.session.add(insertdata) mysqlpool.session.commit() except Exception as e: logmsg = "数据库新增申请账户记录数据失败,失败原因:" + repr(e) api_logger.error(logmsg) return ApiError.requestfail_server(logmsg) # 4.如果账户存在但状态为未激活,则将先前的账户操作记录数据置为无效,然后插入新的未完成的操作记录 elif uinfo_mysql.userStatus == 0: # 查询关键操作唯一标识符 odata = ApiCheck.check_operate( appconfig.get("operation_alias", "register")) if odata["exist"] is True: pass elif odata["exist"] is False: return ApiError.requestfail_error("关键操作别名不存在") else: return ApiError.requestfail_server("操作处理异常") # 生成操作码 code = str( uuid.uuid3( uuid.NAMESPACE_DNS, requestvalue_mail + str(datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')))) # 发送包含账户信息确认页链接的邮件 send_result_flag, send_result_type = publicmailer.sendmail_register( uinfo_mysql.userId, requestvalue_mail, code, odata["operationId"]) # 如果发送失败,则返回错误信息 if send_result_flag is False: if send_result_type == -1: return ApiError.requestfail_server("SMTP服务器连接失败") elif send_result_type == 1 or send_result_type == 2: return ApiError.requestfail_server("公共邮箱登陆失败") elif send_result_type == 3: return ApiError.requestfail_error("邮件发送失败,请检查邮箱地址") # 查询mysql中的操作记录 try: rdata_mysql = model_mysql_useroperationrecord.query.filter_by( userId=uinfo_mysql.userId, operationId=odata["operationId"], recordStatus=0).all() except Exception as e: logmsg = "账户操作记录数据查询失败,失败原因:" + repr(e) api_logger.error(logmsg) return ApiError.requestfail_server(logmsg) # 如果查询到了,则全部置为无效 if rdata_mysql is not None: for d in rdata_mysql: d.recordStatus = -1 try: mysqlpool.session.commit() except Exception as e: logmsg = "账户操作记录数据更新失败,失败原因:" + repr(e) api_logger.error(logmsg) return ApiError.requestfail_server(logmsg) # 将新操作码数据写入mysql insertdata = model_mysql_useroperationrecord( userId=uinfo_mysql.userId, operationId=odata["operationId"], recordCode=code, recordStatus=0, recordValidTime=( datetime.datetime.now() + datetime.timedelta(days=1)).strftime('%Y-%m-%d %H:%M:%S')) try: mysqlpool.session.add(insertdata) mysqlpool.session.commit() except Exception as e: logmsg = "账户操作记录数据新增失败,失败原因:" + repr(e) api_logger.error(logmsg) return ApiError.requestfail_server(logmsg) # 5.如果账户存在且状态不为未激活,则将告知前端账户已存在 else: return ApiError.requestfail_error("账户已存在") # 定义msg response_json["msg"] = "操作成功,请查收账户注册邮件" # 最后返回内容 return response_json