def server_index(): req = request.values kw = req.get("kw", "").strip() page = int(req.get("p", 1)) query = JobServer.query if kw: query = query.filter(JobServer.name.ilike('%{}%'.format(kw))) page_params = { "total": query.count(), "page_size": CommonConstant.PAGE_SIZE, "page": page, "display": CommonConstant.PAGE_DISPLAY } pages = UtilHelper.iPagination(page_params) offset = (page - 1) * CommonConstant.PAGE_SIZE limit = CommonConstant.PAGE_SIZE * page list = query.order_by(JobServer.id.desc())[offset:limit] data = [] server_env_map = CommonConstant.server_env_map if list: for item in list: tmp_data = ModelHelper.model2Dict(item) tmp_env_ids = (item.env).strip( CommonConstant.special_strike).split( CommonConstant.special_strike) tmp_env_list = [] for _env_id in tmp_env_ids: if int(_env_id) not in server_env_map.keys(): continue tmp_env_list.append(server_env_map.get(int(_env_id))) tmp_data['env'] = ",".join(tmp_env_list) data.append(tmp_data) sc = {'kw': kw} set_flag = RBACService.checkPageRelatePrivilege("set") ops_flag = RBACService.checkPageRelatePrivilege("ops") return UtilHelper.renderView( "home/job/server/index.html", { "list": data, "pages": pages, "server_env_map": CommonConstant.server_env_map, "sc": sc, "set_flag": set_flag, "ops_flag": ops_flag })
def tools_alert(): req = request.values page = int(req.get("p", 1)) date_from = req.get("date_from", DateHelper.getCurrentTime(fmt="%Y-%m-%d")) date_to = req.get("date_to", DateHelper.getCurrentTime(fmt="%Y-%m-%d")) status = int(req.get("status", CommonConstant.default_status_neg_99)) query = JobAlertList.query.filter( JobAlertList.created_time.between(date_from, date_to + " 23:59:59")) if status > CommonConstant.default_status_neg_99: query = query.filter_by(status=status) page_params = { "total": query.count(), "page_size": CommonConstant.PAGE_SIZE, "page": page, "display": CommonConstant.PAGE_DISPLAY, } pages = UtilHelper.iPagination(page_params) offset = (page - 1) * CommonConstant.PAGE_SIZE limit = CommonConstant.PAGE_SIZE * page list = query.order_by(JobAlertList.id.desc())[offset:limit] data = [] if list: job_ids = ModelHelper.getFieldList(list, "job_id") job_map = ModelHelper.getDictFilterField(JobList, select_field=JobList.id, id_list=job_ids.sort()) for item in list: tmp_data = ModelHelper.model2Dict(item) tmp_job_info = ModelHelper.model2Dict( job_map.get(tmp_data['job_id'])) tmp_data['status_desc'] = CommonConstant.common_status_map4[ tmp_data['status']] tmp_data['job_name'] = tmp_job_info['name'] data.append(tmp_data) sc = {'date_from': date_from, 'date_to': date_to, 'status': status} return UtilHelper.renderView( "home/job/tools/alert.html", { "list": data, "pages": pages, "sc": sc, "status_map": CommonConstant.common_status_map4, "current": "alert" })
def news_ops(): req = request.values id = int(req['id']) if ('id' in req and req['id']) else 0 if not id: return UtilHelper.renderErrJSON( CommonConstant.SYSTEM_DEFAULT_ERROR ) info = UserNews.query.filter_by( id = id,uid = CurrentUserService.getUid() ).first() if not info: return UtilHelper.renderErrJSON( "指定站内信不存在" ) info.status = CommonConstant.default_status_true db.session.add( info ) db.session.commit() return UtilHelper.renderSucJSON()
def home_release(): release_list = [ { "title": "V1.3 上线", "date": "2020-11-01", "content": "监控常驻job内存消耗<br/>强制杀死job" }, { "title": "V1.2 上线", "date": "2020-10-20", "content": "增加常驻Job<br/>核心调度Job日志使用logrotate管理" }, { "title": "V1.1 上线", "date": "2020-10-14", "content": "增加Job分类管理,每个Job需要所属组<br/>增加钉钉和企业微信报警配置" }, { "title": "V1.0 上线", "date": "2020-10-03", "content": "Job管理调度平台 正式上线<br/>服务器管理、Job管理、Job工具、异常监控" }, { "title": "V0.1", "date": "2020-09-22", "content": "基础功能(员工管理、RBAC、日志管理、站内信、网址之家等)基于个人开源Python3 CMS,<a target='_blank' href='http://dcenter.jixuejima.cn/#/flask/v2/readme'>详情点击了解</a>" } ] return UtilHelper.renderView("home/index/release.html",{ "list" : release_list, "count" : len( release_list ) })
def dept_index(): dept_list = Role.query.order_by(Role.pid.asc()).all() list = [] if dept_list: dept_data = {} for item in dept_list: if not item.pid and item.id not in dept_data: dept_data[item.id] = { "self": item, "sub": [] } if item.pid: dept_data[item.pid]['sub'].append( item ) for item in dept_data.values(): list.append( item['self'] ) list.extend( item['sub']) set_flag = RBACService.checkPageRelatePrivilege("set") ops_flag = RBACService.checkPageRelatePrivilege("ops") return UtilHelper.renderView("home/rbac/dept/index.html", { "list": list, "set_flag": set_flag, "ops_flag": ops_flag, } )
def home_index(): date = DateHelper.getCurrentTime(fmt="%Y-%m-%d") job_count = JobList.query.filter_by(is_del=CommonConstant.default_status_false).count() server_count = JobServer.query.filter_by(status=CommonConstant.default_status_true).count() alert_count = JobAlertList.query.filter(JobAlertList.created_time.between(date, date + " 23:59:59")).count() cate_map = ModelHelper.getDictFilterField( JobCategory ) cat_job_map = {} cat_job_list = JobList.query.with_entities(JobList.cate_id ,func.count( JobList.id) )\ .filter_by(is_del=CommonConstant.default_status_false)\ .group_by(JobList.cate_id).all() if cat_job_list: for _item in cat_job_list: cat_job_map[ _item[0] ] = _item[1] type_job_map = {} job_type_map = CommonConstant.job_type_map type_job_list = JobList.query.with_entities(JobList.job_type, func.count(JobList.id)) \ .filter_by(is_del=CommonConstant.default_status_false) \ .group_by(JobList.job_type).all() if type_job_list: for _item in type_job_list: type_job_map[ _item[0] ] = _item[1] return UtilHelper.renderView("home/index/index.html", { "job_count": job_count, "server_count": server_count, "alert_count": alert_count, 'cate_map' : cate_map, 'cat_job_map' : cat_job_map, 'job_type_map' : job_type_map, 'type_job_map' : type_job_map, })
def tools_index(): list = JobList.query.filter_by( run_status=CommonConstant.default_status_pos_2).order_by( JobList.id.desc()).all() return UtilHelper.renderView("home/job/tools/index.html", { "list": list, "current": "index" })
def job_info(): req = request.values id = int(req['id']) if ('id' in req and req['id']) else 0 info = JobList.query.filter_by(id=id).first() if not info: return redirect(GlobalUrlService.buildHomeUrl("/job/index/index")) info = ModelHelper.model2Dict(info) server_info = JobServer.query.filter_by(id=info['server_id']).first() cate_info = JobCategory.query.filter_by(id=info['cate_id']).first() server_env_map = CommonConstant.server_env_map run_status_map = CommonConstant.run_status_map info['next_run_time'] = DateHelper.getDateOnTimestamps( info['next_run_time'], '%Y-%m-%d %H:%M') info['env_name'] = server_env_map.get(info['env_id']) info['run_status_desc'] = run_status_map.get(info['run_status']) info['job_status_desc'] = job_status_map.get(info['status']) info['server_name'] = server_info.name info['cate_name'] = cate_info.name if cate_info else '' info['run_interval_desc'] = DateHelper.formatBeautyTime( info['run_interval'] * 60) user_map = ModelHelper.getDictFilterField( User, select_field=User.id, id_list=[info['owner_uid'], info['relate_uid']]) ##获取最近5天运行记录 log_list = JobRunLog.query.filter_by(job_id=id).order_by( JobRunLog.id.desc())[0:5] log_data = [] if log_list: for item in log_list: tmp_data = ModelHelper.model2Dict(item) tmp_data['status_desc'] = CommonConstant.job_log_status_map[ tmp_data['status']] tmp_data['duration'] = "" if DateHelper.getCurrentTime(date=tmp_data['end_time'] ) == CommonConstant.DEFAULT_DATETIME: tmp_data['end_time'] = "未知" tmp_data['duration'] = time.time() - time.mktime( tmp_data['start_time'].timetuple()) else: tmp_data['duration'] = tmp_data['end_time'].timestamp( ) - tmp_data['start_time'].timestamp() tmp_data['duration'] = DateHelper.formatBeautyTime( tmp_data['duration']) log_data.append(tmp_data) return UtilHelper.renderView( "home/job/index/info.html", { "info": info, "log_list": log_data, "user_map": user_map, "job_level_map": CommonConstant.job_level_map, })
def staff_set(): if UtilHelper.isGet() : req = request.values id = int( req['id'] ) if ( 'id' in req and req['id'] )else 0 info = None if id > 0: info = User.query.filter_by( id=id ).first() ##部门 dept_list = Role.query.order_by( Role.pid.asc() ).all() dept_data = {} if dept_list: for item in dept_list: if not item.pid and item.id not in dept_data: dept_data[ item.id ] = { "name": item.name, "sub" : [] } if item.pid: dept_data[item.pid]['sub'].append( { "id":item.id,"name": item.name } ) return UtilHelper.renderPopView( "home/rbac/staff/set.html",{ "info":info,"dept_list":dept_data } ) req = request.values id = int(req['id']) if ('id' in req and req['id']) else 0 name = req.get("name","").strip() email = req.get("email","").strip() role_id = int( req.get("role_id",0 ) ) if not ValidateHelper.validLength( name,1,10 ): return UtilHelper.renderErrJSON("请输入符合规范的姓名~~") if not ValidateHelper.validEMail( email ): return UtilHelper.renderErrJSON("请输入符合规范的邮箱~~") if role_id < 1: return UtilHelper.renderErrJSON("请选择部门(顶级部门不可选择)~~") has_in = User.query.filter(User.email == email, User.id != id).first() if has_in: return UtilHelper.renderErrJSON("该邮箱已存在,请换一个再试~~") info = User.query.filter_by(id=id).first() if info: model_user = info else: model_user = User() if not model_user.salt: model_user.salt = CurrentUserService.geneSalt() model_user.name = name model_user.email = email model_user.role_id = role_id db.session.add( model_user ) db.session.commit() return UtilHelper.renderSucJSON()
def set_info(): if UtilHelper.isGet(): return UtilHelper.renderPopView("home/user/profile/set_info.html", {"info": CurrentUserService.getInfo() }) req = request.values name = req.get("name", "").strip() email = req.get("email", "").strip() if not ValidateHelper.validLength(name, 1, 10): return UtilHelper.renderErrJSON("请输入符合规范的姓名~~") if not ValidateHelper.validEMail(email): return UtilHelper.renderErrJSON("请输入符合规范的邮箱~~") info = CurrentUserService.getInfo() if not info: return UtilHelper.renderErrJSON( CommonConstant.SYSTEM_DEFAULT_ERROR ) has_in = User.query.filter(User.email == email, User.id != info.id ).first() if has_in: return UtilHelper.renderErrJSON("该邮箱已存在,请换一个再试~~") info.name = name info.email = email db.session.add(info) db.session.commit() return UtilHelper.renderSucJSON()
def home_news(): query = UserNews.query.filter_by(uid=CurrentUserService.getUid(), status=CommonConstant.default_status_false) total = query.count() list = query.order_by(UserNews.id.desc()).all() data = [] if list: for item in list: tmp_content = "<h5 class='text-danger'>标题:%s</h5><br/>%s<br/>时间:%s" % ( item.title, item.content, item.created_time) tmp_data = { "id": item.id, "title": item.title, "content": tmp_content, "created_time": DateHelper.getFormatDate(DateHelper.str2Date(item.created_time), format="%m-%d %H:%M"), } data.append(tmp_data) content = UtilHelper.renderView("home/index/news.html", {"list": data, "total": total}) return UtilHelper.renderSucJSON({"total": total, "content": content})
def Login(): if request.method == "GET": if g.current_user: return redirect(GlobalUrlService.buildHomeUrl("/")) return UtilHelper.renderView("home/user/login_2.html") resp = {'code': 200, 'msg': '操作成功~~', 'data': {}} req = request.values email = req['email'] if 'email' in req else '' pwd = req['pwd'] if 'pwd' in req else '' if email is None or len(email) < 1: resp['code'] = -1 resp['msg'] = "请输入正确的邮箱~~" return jsonify(resp) if pwd is None or len(pwd) < 1: resp['code'] = -1 resp['msg'] = "请输入正确的邮箱密码~~" return jsonify(resp) user_info = User.query.filter_by( email=email, status=CommonConstant.default_status_true).first() if not user_info: resp['code'] = -1 resp['msg'] = "你好,未注册的邮箱,请找系统管理员先注册用户~~" return jsonify(resp) try: at_idx = email.index("@") smtp_obj = smtplib.SMTP_SSL("smtp." + email[(at_idx + 1):], 465) smtp_obj.set_debuglevel(1) smtp_obj.login(email, pwd) smtp_obj.close() except Exception: resp['code'] = -1 resp['msg'] = "登录失败,请核对邮箱和密码是否对应~~" return jsonify(resp) next_url = GlobalUrlService.buildHomeUrl("/") response = make_response( json.dumps({ 'code': 200, 'msg': '登录成功~~', 'data': { "next_url": next_url } })) response.set_cookie( CommonConstant.AUTH_COOKIE_NAME, '%s#%s' % (CurrentUserService.userAuthToken(user_info), user_info.id), 60 * 60 * 24 * 120) # 保存120天 return response
def dept_set(): if UtilHelper.isGet() : req = request.values id = int( req['id'] ) if ( 'id' in req and req['id'] )else 0 info = None query_role_list = Role.query.filter_by( pid = CommonConstant.default_status_false ) if id > 0: info = Role.query.filter_by( id=id ).first() query_role_list = query_role_list.filter( Role.id != id ) role_list = query_role_list.order_by( Role.id.desc() ).all() return UtilHelper.renderPopView( "home/rbac/dept/set.html",{ "info":info ,"role_list": role_list} ) req = request.values id = int(req['id']) if ('id' in req and req['id']) else 0 name = req.get("name","").strip() pid = int( req.get("pid","0").strip() ) if not ValidateHelper.validLength( name,1,10 ): return UtilHelper.renderErrJSON("请输入符合规范的姓名~~") info = Role.query.filter_by(id=id).first() if info: model_role = info #还不能选择自己的子节点 if id == pid: return UtilHelper.renderErrJSON("不能勾选自己为所属部门哦~~") else: model_role = Role() model_role.name = name model_role.pid = pid db.session.add( model_role ) db.session.commit() return UtilHelper.renderSucJSON()
def grant_ops(): req = request.values id = int(req['id']) if ('id' in req and req['id']) else 0 act = req.get("act", "").strip() allow_act = ['del', 'recovery'] if not id: return UtilHelper.renderErrJSON(CommonConstant.SYSTEM_DEFAULT_ERROR) if act not in allow_act: return UtilHelper.renderErrJSON(CommonConstant.SYSTEM_DEFAULT_ERROR) info = Action.query.filter_by(id=id).first() if not info: return UtilHelper.renderErrJSON("指定权限不存在") if act == "del": info.status = CommonConstant.default_status_false elif act == "recovery": info.status = CommonConstant.default_status_true db.session.add(info) db.session.commit() return UtilHelper.renderSucJSON()
def staff_index(): req = request.values kw = req.get("kw", "").strip() page = int(req.get("p", 1)) query = User.query if kw: query = query.filter( or_( User.name.ilike( '%{}%'.format(kw) ) ,User.email.ilike( '%{}%'.format(kw) ) )) page_params = { "total": query.count(), "page_size": CommonConstant.PAGE_SIZE, "page": page, "display": CommonConstant.PAGE_DISPLAY, } pages = UtilHelper.iPagination(page_params) offset = (page - 1) * CommonConstant.PAGE_SIZE limit = CommonConstant.PAGE_SIZE * page list = query.order_by( User.id.desc() )[offset:limit] dept_map = ModelHelper.getDictFilterField( Role ) sc = { 'kw': kw } set_flag = RBACService.checkPageRelatePrivilege("set") ops_flag = RBACService.checkPageRelatePrivilege("ops") return UtilHelper.renderView( "home/rbac/staff/index.html", { "list": list, "pages": pages, "dept_map" : dept_map, "sc": sc, "set_flag": set_flag, "ops_flag": ops_flag, })
def before_request(): ignore_urls = app.config['IGNORE_URLS_HOME'] ignore_check_login_urls = app.config['IGNORE_CHECK_LOGIN_URLS'] path = request.path #如果是静态文件就不要查询用户信息了 pattern = re.compile('%s' % "|".join(ignore_check_login_urls)) if pattern.match(path) or "/home" not in path: return # 多查询一次数据也没有什么问题 user_info = check_login() g.current_user = None if user_info: g.current_user = user_info #将忽略数组换成字符串 pattern = re.compile('%s' % "|".join(ignore_urls)) if pattern.match(path): return if not user_info: response = make_response( redirect(GlobalUrlService.buildHomeUrl("/user/logout"))) return response #判断RBAC的权限 if not RBACService.checkPrivilege(path): if UtilHelper.isAjax(): return UtilHelper.renderErrJSON("无权限,请联系管理员") response = make_response( redirect(GlobalUrlService.buildHomeUrl("/error/ban", {"msg": path}))) return response g.menus = MenuServiceService.getMenu() AppLogService.addAccessLog(user_info) return
def grant_set(): if UtilHelper.isGet(): req = request.values id = int(req['id']) if ('id' in req and req['id']) else 0 act = req.get("act", "").strip() info = None if id > 0: info = Action.query.filter_by(id=id).first() weight_list = [1] weight_list.extend(range(5, 80, 5)) if act == "copy" and info: info.id = 0 return UtilHelper.renderPopView("home/rbac/grant/set.html", { "info": info, "weight_list": weight_list, }) req = request.values id = int(req['id']) if ('id' in req and req['id']) else 0 level1_name = req.get("level1_name", "").strip() level2_name = req.get("level2_name", "").strip() name = req.get("name", "").strip() url = req.get("url", "").strip() level1_weight = int(req.get("level1_weight", "1").strip()) level2_weight = int(req.get("level2_weight", "1").strip()) weight = int(req.get("weight", "1").strip()) if not ValidateHelper.validLength(level1_name, 1, 20): return UtilHelper.renderErrJSON("请输入符合规范的一级菜单名称~~") if not ValidateHelper.validLength(level2_name, 1, 20): return UtilHelper.renderErrJSON("请输入符合规范的二级菜单名称~~") if not ValidateHelper.validLength(name, 1, 20): return UtilHelper.renderErrJSON("请输入符合规范的权限名称~~") info = Action.query.filter_by(id=id).first() if info: model_action = info else: model_action = Action() model_action.level1_name = level1_name model_action.level2_name = level2_name model_action.name = name model_action.url = url.replace("\r\n", ",") model_action.level1_weight = level1_weight model_action.level2_weight = level2_weight model_action.weight = weight db.session.add(model_action) db.session.commit() return UtilHelper.renderSucJSON()
def residentProcess(self, item_model): if item_model['job_type'] != CommonConstant.default_status_pos_2: return False job_id = item_model['id'] pid_file = self.getPidPath('job_%s.pid' % job_id) pid = 0 if self.checkPidExist(pid_file): pid = self.findPidByKw(job_id) info = JobRunLog.query.filter_by( job_id = job_id ,status = CommonConstant.default_status_neg_1 )\ .order_by( JobRunLog.id.desc() ).limit(1).first() if info: job_used_mem = UtilHelper.getUsedMemory(pid) info.max_mem = job_used_mem db.session.add(info) db.session.commit() return True
def link_set(): if UtilHelper.isGet(): req = request.values id = int(req['id']) if ('id' in req and req['id']) else 0 info = None if id > 0: info = Link.query.filter_by(id=id).first() return UtilHelper.renderPopView( "home/link/set.html", { "info": info, "type_map": CommonConstant.link_type_map }) req = request.values id = int(req['id']) if ('id' in req and req['id']) else 0 type = int(req.get("type", 0).strip()) title = req.get("title", "").strip() url = req.get("url", "").strip() weight = int(req.get("weight", 1).strip()) if type < 1: return UtilHelper.renderErrJSON("请选择分类~~") if not ValidateHelper.validLength(title, 1, 30): return UtilHelper.renderErrJSON("请输入符合规范的标题~~") if not ValidateHelper.validUrl(url): return UtilHelper.renderErrJSON("请输入符合规范的网址~~") info = Link.query.filter_by(id=id).first() if info: model_link = info else: model_link = Link() model_link.type = type model_link.title = title model_link.url = url model_link.weight = weight db.session.add(model_link) db.session.commit() return UtilHelper.renderSucJSON()
def home_index(): return UtilHelper.renderView("home/index/index.html")
def grant_assign(): if UtilHelper.isGet(): req = request.values role_id = int(req.get("role_id", 0)) role_pid = int(req.get("role_pid", 0)) ''' 取出来所有的一级部门 ''' p_role_list = Role.query.filter_by(pid=CommonConstant.default_status_false)\ .order_by( Role.id.asc() ).all() if not role_pid and p_role_list: #如果没有父部门,那就选择一个 role_pid = p_role_list[0].id sub_role_list = Role.query.filter_by( pid = role_pid)\ .order_by( Role.id.asc() ).all() if not role_id and sub_role_list: role_id = sub_role_list[0].id user_list = User.query.filter_by( status=CommonConstant.default_status_true, role_id=role_id).all() action_list = Action.query.filter_by( status = CommonConstant.default_status_true )\ .order_by( Action.level1_weight.desc(),Action.level2_weight.desc(),Action.weight.desc() ).all() action_data = {} if action_list: for item in action_list: tmp_level1_key = item.level1_name tmp_level2_key = item.level2_name if tmp_level1_key not in action_data: action_data[tmp_level1_key] = { "name": tmp_level1_key, "counter": 0, "sub": {} } if tmp_level2_key not in action_data[tmp_level1_key]['sub']: action_data[tmp_level1_key]['sub'][tmp_level2_key] = { "name": tmp_level2_key, "counter": 0, "act_list": [] } action_data[tmp_level1_key]['counter'] += 1 action_data[tmp_level1_key]['sub'][tmp_level2_key][ 'counter'] += 1 tmp_data = { "id": item.id, "name": item.name, "is_important": item.is_important } action_data[tmp_level1_key]['sub'][tmp_level2_key][ 'act_list'].append(tmp_data) owned_act = RoleAction.query.filter_by( role_id=role_id, status=CommonConstant.default_status_true).all() owned_act_ids = ModelHelper.getFieldList(owned_act, 'action_id') sc = { "role_id": role_id, "role_pid": role_pid, } return UtilHelper.renderView( "home/rbac/grant/assign.html", { "list": action_data, "p_role_list": p_role_list, "sub_role_list": sub_role_list, "user_list": user_list, "owned_act_ids": owned_act_ids, "sc": sc }) req = request.values role_id = int(req.get("role_id", 0)) action_ids = request.form.getlist("action_ids[]") action_ids = list(map(int, action_ids)) if not role_id or role_id < 1: return UtilHelper.renderErrJSON("请选择部门在分配权限~~") info = Role.query.filter_by(id=role_id).first() if not info: return UtilHelper.renderErrJSON("请选择部门在分配权限 -2~~") ###分配权限逻辑还是挺复杂的 ## 已有的权限 owned_act = RoleAction.query.filter_by(role_id=role_id).all() owned_act_ids = ModelHelper.getFieldList(owned_act, 'action_id') ''' 找出删除的权限(生产环境数据库没有删除权限) 假如已有的权限集合是A,界面传递过得权限集合是B 权限集合A当中的某个权限不在权限集合B当中,就应该删除 计算差集 ''' delete_act_ids = list(set(owned_act_ids) - set(action_ids)) if delete_act_ids: RoleAction.query.filter( RoleAction.role_id == role_id,RoleAction.action_id.in_( delete_act_ids ) )\ .update({ "status":CommonConstant.default_status_false },synchronize_session = False) db.session.commit() ''' 找出添加的权限 假如已有的权限集合是A,界面传递过得权限集合是B 权限集合B当中的某个权限不在权限集合A当中,就应该添加 计算差集 ''' add_act_ids = list(set(action_ids) - set(owned_act_ids)) if add_act_ids: for _action_id in add_act_ids: _model_role_action = RoleAction() _model_role_action.role_id = role_id _model_role_action.action_id = _action_id db.session.add(_model_role_action) db.session.commit() ''' 找出需要更新的权限(生产环境数据库没有删除权限) 假如已有的权限集合是A,界面传递过得权限集合是B 权限集合B当中的某个权限也在在权限集合A当中,就应该更新 计算补集 ''' update_act_ids = list(set(owned_act_ids).intersection(set(action_ids))) if update_act_ids: RoleAction.query.filter(RoleAction.role_id == role_id, RoleAction.action_id.in_(update_act_ids)) \ .update({"status": CommonConstant.default_status_true}, synchronize_session=False) db.session.commit() return UtilHelper.renderSucJSON({}, "权限分配成功~~")
def news_batch_ops(): UserNews.query.filter_by( uid = CurrentUserService.getUid() ).update({"status": CommonConstant.default_status_true }) db.session.commit() return UtilHelper.renderSucJSON()
def run(self, params): pid_path = self.getPidPath('dispatch.pid') if self.checkPidExist(pid_path): app.logger.info("[core] dispatch is running") return False pid = str(os.getpid()) if not self.setPidFile(pid_path, pid): err_msg = self.getErrMsg() app.logger.info("Cann't get a lock file,err msg : " + err_msg) return False params = self.getEnvFile() server_id = params['id'] host = params['name'] list = JobList.query.filter_by( server_id = server_id,status = CommonConstant.default_status_true, run_status = CommonConstant.default_status_true,is_del = CommonConstant.default_status_false ).all() if not list: app.logger.info("没有数据需要调度~~") return True for t in list: ##调度时间是否到了,应该加入到SQL查询中查询 if t.next_run_time >= time.time(): app.logger.info( "job_id:%s,运行时间未到"%( t.id ) ) continue # 启子进程中运行 app.logger.info( "get a task: job_id:%s,运行时间:%s" % (t.id,DateHelper.getCurrentTime()) ) ''' 子进程复制一份父进程内存给自己,两个进程之间的执行是相互独立的,其执行顺序可以是不确定的、随机的、不可预测的 多进程(os.fork())下,子进程会继承父进程的连接,所以会有问题.先销毁已有的engine,确保父进程没有数据库连接 相关错误:Mysql server has gone away ''' self.closePoolDB() pid = os.fork() if pid == 0: #子进程,这里是一个独立进程(在复制出来的那一刻 所有变量都会共享到子进程),所以写代码 就要感觉在一个独立方法中 self.closePoolDB() job_id = t.id job_pid_file = self.getPidPath( 'job_%s.pid' % job_id ) if self.checkPidExist(job_pid_file): app.logger.info("job_id:%s is running on %s" % (job_id, host)) return 0 ## 建立具体job的pid 文件,防止重复运行,这个进程id其实记录的是不对的,应该使用下面的 tmp_pid = str(os.getpid()) if not self.setPidFile(job_pid_file, tmp_pid): app.logger.info("job_id:%s 不能建立pid,path:%s,msg:%s" % (job_id, job_pid_file, self.getErrMsg())) return True app.logger.info("job_id:%s 建立pid,子进程pid:%s" % (job_id, tmp_pid)) ## 更新job为运行中 try: tmp_affect_rows = JobList.query.filter_by( id = job_id,run_status = CommonConstant.default_status_true )\ .update( dict( run_status = CommonConstant.default_status_pos_2 ) ) db.session.commit() if tmp_affect_rows < 1: app.logger.info("job_id:%s不能得到lock,任务已经运行中" % job_id) return False except: app.logger.info( "job_id:%s不能得到锁状态,err:%s" % (job_id,str( sys.exc_info() ) ) ) ##写入一条调度日志 tmp_log_id = 0 try: tmp_log_params = { "job_id":job_id, "server_id":server_id, "server_name":host, "status": CommonConstant.default_status_neg_1, "start_time":DateHelper.getCurrentTime() } tmp_log_id = JobService.addRunLog( tmp_log_params ) except : pass self.closePoolDB() tmp_job_run_start_time = time.time() # job开始运行的时间 # t.command无法获取job内部输出的内容,我们需要按行读取或者按buffer读取的 # status = os.system(t.command)>>8#status, output = commands.getstatusoutput(t.command) # 可以加 bufsize = -1 表示使用系统默认缓存 # 命令前面加一下前缀,方便搜索关键词查找 # 创建子进程后子进程不结束 https://bbs.csdn.net/topics/390596479?_=1515055076 tmp_command = t.command tmp_command = "tmp_job_%s='%s' && %s"%( job_id,DateHelper.getCurrentTime(),tmp_command) #如果想要达到2>&1 可以设置为stdout=subprocess.PIPE,stderr=subprocess.STDOUT sp = subprocess.Popen(tmp_command, bufsize = -1, shell = True, close_fds=True, stdout=subprocess.PIPE,stderr=subprocess.STDOUT) tmp_run_job_pid = sp.pid #上面存的关于job的进程id 是不对的,这里在覆盖一次 self.coverPidFile(job_pid_file,tmp_run_job_pid) ''' 如果是包裹了一层runshell的需要找到进程的子进程pid,然后在查看内存 tmp_pid 是目前子进程的进程号 tmp_run_job_pid 是目前 subprocess启动的进程好 真真运行的进程号,需要通过关键词查询,所以在命令前面加了特别东西 ''' app.logger.info( "job_id:%s 启动Job脚本,pid:%s" % (job_id, tmp_run_job_pid)) ##统计内存占用量 tmp_max_job_used_mem = tmp_job_used_mem = UtilHelper.getUsedMemory( tmp_run_job_pid ) app.logger.info("job_id:%s 日志start-------" %job_id ) ''' sp.poll() 返回值 0 正常结束 1 sleep 2 子进程不存在 -15 kill None 在运行 判断进程状态 ''' while sp.poll() is None: ##统计内存占用量 tmp_job_used_mem = UtilHelper.getUsedMemory( tmp_run_job_pid ) if tmp_job_used_mem > tmp_max_job_used_mem: tmp_max_job_used_mem = tmp_job_used_mem tmp_line_output = sp.stdout.readline() tmp_line_output = tmp_line_output.strip() #返回的是bytes tmp_line_output = str(tmp_line_output, encoding="utf8") tmp_lines = tmp_line_output.split("\n") for tmp_line in tmp_lines: app.logger.info("job_id:%s %s" % (job_id, tmp_line) ) app.logger.info("job_id:%s 日志end-------" % job_id) ##统计内存占用量 tmp_job_used_mem = UtilHelper.getUsedMemory( tmp_run_job_pid ) if tmp_job_used_mem > tmp_max_job_used_mem: tmp_max_job_used_mem = tmp_job_used_mem app.logger.info("job_id:%s PID:%s, 使用内存(end) %s" % (job_id, tmp_run_job_pid, tmp_job_used_mem)) app.logger.info("job_id:%s PID:%s, 最大使用内存 %s" % (job_id, tmp_run_job_pid, tmp_max_job_used_mem)) app.logger.info("job_id:%s 更新消耗内存完毕" % (job_id)) # 将标准输出关闭了 sp.stdout.close() tmp_status = sp.wait() app.logger.info("job_id:%s status_code:%s,%s" % (t.id, str(tmp_status),tmp_command )) #和下面分开就是怕报警影响正常处理 try: #杀死常驻job也会发生 MySQL server has gone away,只要运行的时间太长就会出问题了 self.closePoolDB() #相关报警判断 self.alertStatusJudge(t, tmp_status) self.alertRunTimeJudge(t, tmp_job_run_start_time) except: app.logger.info( self.getErrMsg() ) # 更新状态和下一次运行时间 try: self.closePoolDB() ##提前将文件释放下,因为当服务器状态非常繁忙的时候,进程比较缓慢,会导致状态已经更新但是pid文件没有删除 self.atexit_removepid(job_pid_file) if int( t.job_type ) == CommonConstant.default_status_pos_3 :#一次性job JobList.query.filter_by(id=job_id).update( dict( run_status = CommonConstant.default_status_false,status = CommonConstant.default_status_false) ) db.session.commit() else: if int( t.job_type ) == CommonConstant.default_status_pos_2: # 常驻Job,他停止之后下一分钟直接运行 tmp_next_time = datetime.datetime.now() + datetime.timedelta(minutes=1) tmp_next_time = tmp_next_time.replace(second=0) tmp_next_time = int( time.mktime(tmp_next_time.timetuple() ) ) else: tmp_next_time = t.next_run_time + int( math.ceil((time.time() - t.next_run_time) / (t.run_interval * 60)) * t.run_interval * 60) JobList.query.filter_by(id=job_id).update( dict( run_status = CommonConstant.default_status_true ,next_run_time = tmp_next_time ) ) db.session.commit() ##更新对应日志的log,担心出错影响其他 JobService.updateRunLog(tmp_log_id, tmp_max_job_used_mem, (tmp_status == 0)) except: app.logger.info( self.getErrMsg() ) # 完成 self.closePoolDB() app.logger.info('job_id:%s 运行完成时间为:%s,子进程结束~~' % (job_id, DateHelper.getCurrentTime() )) return 0 elif pid > 0: # 父进程 ''' status是一个传出参数。 waitpid的pid参数选择: < -1 回收指定进程组内的任意子进程 = -1 回收任意子进程,等待所有的子进程终止 = 0 回收和当前调用waitpid一个组的所有子进程 > 0 回收指定ID的子进程 ''' app.logger.info("父进程 job_id:%s pid:%s" % (t.id, pid)) #os.waitpid( pid , os.WNOHANG) os.waitpid(-1, os.WNOHANG) app.logger.info("job_id:%s 父进程结束~~" % t.id) else: app.logger.info("job_id:%s,不能建立调度器" % (t.id)) app.logger.info("it's over~~") return True
def home_index(): return UtilHelper.renderView( "home/user/profile/index.html",{ "info":CurrentUserService.getInfo() } )
def tools_log(): status_map = CommonConstant.job_log_status_map req = request.values page = int(req.get("p", 1)) date_from = req.get("date_from", DateHelper.getCurrentTime(fmt="%Y-%m-%d")) date_to = req.get("date_to", DateHelper.getCurrentTime(fmt="%Y-%m-%d")) status = int(req.get("status", CommonConstant.default_status_neg_99)) job_id = int(req.get("job_id", CommonConstant.default_status_false)) query = JobRunLog.query.filter( JobRunLog.created_time.between(date_from, date_to + " 23:59:59")) if job_id: query = query.filter_by(job_id=job_id) if status > CommonConstant.default_status_neg_99: query = query.filter_by(status=status) page_params = { "total": query.count(), "page_size": CommonConstant.PAGE_SIZE, "page": page, "display": CommonConstant.PAGE_DISPLAY, } pages = UtilHelper.iPagination(page_params) offset = (page - 1) * CommonConstant.PAGE_SIZE limit = CommonConstant.PAGE_SIZE * page list = query.order_by(JobRunLog.id.desc())[offset:limit] data = [] if list: job_ids = ModelHelper.getFieldList(list, "job_id") job_map = ModelHelper.getDictFilterField(JobList, select_field=JobList.id, id_list=job_ids.sort()) for item in list: tmp_data = ModelHelper.model2Dict(item) tmp_job_info = ModelHelper.model2Dict( job_map.get(tmp_data['job_id'])) tmp_data['status_desc'] = status_map[tmp_data['status']] tmp_data['job_name'] = tmp_job_info['name'] tmp_data['duration'] = "" if DateHelper.getCurrentTime(date=tmp_data['end_time'] ) == CommonConstant.DEFAULT_DATETIME: tmp_data['end_time'] = "未知" tmp_data['duration'] = time.time() - time.mktime( tmp_data['start_time'].timetuple()) else: tmp_data['duration'] = (tmp_data['end_time'].timestamp() - tmp_data['start_time'].timestamp()) tmp_data['duration'] = DateHelper.formatBeautyTime( tmp_data['duration']) data.append(tmp_data) sc = { 'date_from': date_from, 'date_to': date_to, 'status': status, 'job_id': job_id } return UtilHelper.renderView( "home/job/tools/log.html", { "list": data, "pages": pages, "sc": sc, "status_map": status_map, "current": "log" })
def error_404(e): err_msg = getErrMsg() AppLogService.addErrLog(err_msg) return UtilHelper.renderView( "home/error/error.html",{ "status":404,"msg":"很抱歉!,您访问的页面不存在 ~~" } )
def error_502(e): err_msg = getErrMsg() AppLogService.addErrLog(err_msg) return UtilHelper.renderView("home/error/error.html")
def gii_index(): return UtilHelper.renderView("/home/tools/gii/index.html")
def gii_model(): default_path_prefix = "/common/models/" if UtilHelper.isGet(): db.reflect() #dict_keys 转 list table_list = list(db.metadata.tables.keys()) table_list.sort() return UtilHelper.renderView("/home/tools/gii/model.html", { "default_path_prefix": default_path_prefix, "table_list": table_list }) req = request.values table = req.get("table", "").strip() path = req.get("path", "").strip() ##后面这里的数据库做成选择的,因为有多数据库的可能 engine_uri = app.config.get('SQLALCHEMY_DATABASE_URI', '') folder_path = app.root_path + default_path_prefix + path #不存在就新建 if not os.path.exists(folder_path): os.makedirs(folder_path) model_name = (table.replace("-", " ").replace("_", " ").title()).replace(" ", "") model_path = folder_path + "/" + model_name + ".py" #2>&1 标准错误重定向到标准输出, --noinflect 不把复数处理成单数 例如 user_news 会变成 UserNew cmd = 'flask-sqlacodegen "{0}" --noinflect --tables {1} --outfile "{2}" --flask 2>&1'.format( engine_uri, table, model_path) print(cmd) p = os.popen(cmd) out_list = p.readlines() p.close() if out_list and len(out_list) > 0: return UtilHelper.renderErrJSON("失败原因:" + "<br/>".join(out_list)) ##为了不破坏扩展,实现正则替换,读文件,按行替换 if not os.path.exists(model_path): return UtilHelper.renderErrJSON("model文件不存在,无法执行替换~~") try: f = open(model_path) ret = [] ret.append("# coding: utf-8\n") ret.append("from application import db\n\n") ignore_kws = [ "from flask_sqlalchemy", "from sqlalchemy", "SQLAlchemy", "coding: utf-8" ] line_break_kws = ["\n", "\r\n"] for line in f.readlines(): tmp_break_flag = False for _ignore_kw in ignore_kws: if _ignore_kw in line: tmp_break_flag = True break if tmp_break_flag: continue if line in line_break_kws: continue ret.append(line) f.close() ##最后加一些常用方法 common_funcs = ''' def __init__(self, **items): for key in items: if hasattr(self, key): setattr(self, key, items[key]) ''' f = open(model_path, "w", encoding="utf-8") f.write("".join(ret) + common_funcs) f.flush() f.close() except Exception as e: pass return UtilHelper.renderSucJSON()
def error_500(e): err_msg = getErrMsg() AppLogService.addErrLog(err_msg) return UtilHelper.renderView("home/error/error.html",{ "status":500,"msg":"服务器错误" })