def edit_per(): tid = request.argget.all('id').strip() name = request.argget.all('name', '').strip() explain = request.argget.all('explain', '') default = int(request.argget.all('is_default', 0).strip()) position = str_to_num(request.argget.all('position', 0)) s, r = arg_verify(reqargs=[(gettext("name"), name), (gettext("position"), position)], required=True) if not s: return r hightest_pos = get_num_digits(SUPER_PER) if position > hightest_pos and position < 1: data = { 'msg': gettext("Must be an integer greater than 0," " less than or equal to {}".format(hightest_pos)), 'msg_type': "w", "custom_status": 403 } return data data = { "msg": gettext( "The current user permissions are lower than the permissions you want to modify," " without permission to modify"), "msg_type": "w", "custom_status": 401 } user_role = mdbs["user"].db.role.find_one( {"_id": ObjectId(current_user.role_id)}) # 如果当前用户的权限最高位 小于 要修改成的这个角色权重的最高位,是不可以的 permissions = int(math.pow(2, position - 1)) if get_num_digits(user_role["permissions"]) <= get_num_digits(permissions): return data per = { "name": name, "explain": explain, 'value': permissions, "is_default": default } if mdbs["user"].db.permission.find_one({ "name": name, "_id": { "$ne": ObjectId(tid) } }): data = { 'msg': gettext("Permission name already exists"), 'msg_type': "w", "custom_status": 403 } elif mdbs["user"].db.permission.find_one({ "value": permissions, "_id": { "$ne": ObjectId(tid) } }): data = { 'msg': gettext('Location has been used'), 'msg_type': "w", "custom_status": 403 } else: old_per = mdbs["user"].db.permission.find_one({ "_id": ObjectId(tid), "value": { "$exists": True } }) if old_per: old_per_value = old_per["value"] r = mdbs["user"].db.permission.update_one({"_id": ObjectId(tid)}, {"$set": per}) if not r.modified_count: data = { 'msg': gettext("No changes"), 'msg_type': "w", "custom_status": 201 } else: r = update_role_and_api_per(old_per_value, new_per_value=0) updated_rolename = r["updated_rolename"] msg_updated_rolename = gettext( "The role of the chain reaction is: \n") if updated_rolename: for ur in updated_rolename: msg_updated_rolename = '{}, "{}"'.format( msg_updated_rolename, ur) else: msg_updated_rolename = '{} 0'.format(msg_updated_rolename) # 刷新缓存 cache.delete(key=GET_DEFAULT_SYS_PER_CACHE_KEY, db_type="redis") cache.delete(key=GET_ALL_PERS_CACHE_KEY, db_type="redis") data = { 'msg': gettext("The update is successful. {}".format( msg_updated_rolename)), 'msg_type': "s", "custom_status": 201 } else: data = { 'msg': gettext("Update failed"), 'msg_type': "w", "custom_status": 400 } return data
def init_core_module(app, **kwargs): """ 初始化核心模块 :param app: :return: """ csrf_enabled = kwargs.get("csrf_enabled") is_debug = kwargs.get("is_debug") # app config web_start_log.info("Initialize the core module") # 系统必要配置, 优先导入 app.config.from_object(ConfDictToClass(CONFIG["system"], key="value")) app.config.from_object(ConfDictToClass(CONFIG["key"], key="value")) # 数据库 redis.init_app() app.config.from_object(DatabaseConfig()) for name, mdb in mdbs.items(): mdb.init_app(app, config_prefix=name.upper()) # 缓存 app.config.from_object(ConfDictToClass(CONFIG["cache"], key="value")) app.config["CACHE_REDIS"] = redis app.config["CACHE_MONGODB_DBS"] = mdbs["sys"].dbs cache.init_app(app) # Clear CONFIG cache if not is_debug: version_info = mdbs["sys"].db.sys_config.find_one( {"new_version": { "$exists": True }}) ago_time = time.time() - 3600 * 24 ago_time_30m = time.time() - 1800 if version_info["sys_version_of_config"] >= SYS_CONFIG_VERSION \ and version_info["update_time"] > ago_time \ and version_info["update_time"] < ago_time_30m: # 系统正在使用的SYS_CONFIG_VERSION版本和当前机器CONFIG的一样,或更高 # And: 配置24小时内已有更新 # So: 这次不更新 msg = " * [sys configs cache] Not clean cache." \ " The system is using the same or higher configuration version.\n" \ " And it was executed within 24 hours." start_info_print("\033[33m{}\033[0m".format(msg)) web_start_log.warning(msg) else: with app.app_context(): msg = " * Clean configuration cache successfully" cache.delete(CONFIG_CACHE_KEY) cache.delete(PLUG_IN_CONFIG_CACHE_KEY) web_start_log.info(msg) start_info_print(msg) # 异常错误信息 app.config["PRESERVE_CONTEXT_ON_EXCEPTION"] = PRESERVE_CONTEXT_ON_EXCEPTION ################################################### # 在此之前, 任何程序不能调用utils.get_config.py下的方法 ################################################### from apps.core.utils.get_config import get_configs, get_config from apps.core.flask.request import OsrRequestProcess from apps.core.flask.errorhandler import ErrorHandler from apps.core.blueprint import api, admin_view, theme_view, static_html_view, \ static, open_api, admin_static_file from apps.core.flask.routing import RegexConverter from apps.core.flask.routing import push_url_to_db # 最大请求大小 app.config["MAX_CONTENT_LENGTH"] = get_config( "system", "MAX_CONTENT_LENGTH") * 1024 * 1024 # Session会话配置 session_config = get_configs("session") session_config["SESSION_PROTECTION"] = SESSION_PROTECTION session_config["SESSION_COOKIE_PATH"] = SESSION_COOKIE_PATH session_config["SESSION_COOKIE_HTTPONLY"] = SESSION_COOKIE_HTTPONLY session_config["SESSION_COOKIE_SECURE"] = SESSION_COOKIE_SECURE session_config["SESSION_USE_SIGNER"] = SESSION_USE_SIGNER session_config["SESSION_MONGODB_DB"] = mdbs["sys"].name app.config.from_object(ConfDictToClass(session_config)) app.config["SESSION_REDIS"] = redis app.config["SESSION_MONGODB"] = mdbs["sys"].connection sess.init_app(app) rest_session.init_app(app) # 邮件 app.config.from_object(ConfDictToClass(get_configs("email"))) mail.init_app(app) # Csrf token csrf_config = {} if csrf_enabled: csrf_config["CLIENT_TOKEN_AUTH_ENABLED"] = True start_info_print(" * Security authentication is turned on") else: csrf_config["CLIENT_TOKEN_AUTH_ENABLED"] = False start_info_print( "\033[31m WARNING: security verification is turned off\033[0m") # 这两个csrf参数这里关闭,request程序会根据CLIENT_TOKEN_AUTH_ENABLED判断处理 csrf_config["WTF_CSRF_CHECK_DEFAULT"] = False csrf_config["CSRF_ENABLED"] = False csrf_config["WTF_CSRF_METHODS"] = WTF_CSRF_METHODS app.config.from_object(ConfDictToClass(csrf_config)) csrf.init_app(app) # Babel app.config.from_object(ConfDictToClass(get_configs("babel"))) app.config["BABEL_TRANSLATION_DIRECTORIES"] = BABEL_TRANSLATION_DIRECTORIES babel.init_app(app) # 登录管理 login_manager.init_app(app) # login_manager.anonymous_user = AnonymousUser() login_manager.session_protection = SESSION_PROTECTION # oauth.init_app(app) # 让路由支持正则 app.url_map.converters['regex'] = RegexConverter # 注册蓝图 blueprint web_start_log.info("Register blueprint, Initialize the routing") app.register_blueprint(api) app.register_blueprint(open_api) app.register_blueprint(admin_view) app.register_blueprint(theme_view) app.register_blueprint(static_html_view) app.register_blueprint(static) app.register_blueprint(admin_static_file) if not is_debug: st = time.time() push_url_to_db(app) start_info_print( " * Routing updates saved in the database. It tasks time {} sec". format(int(time.time() - st))) celery.conf.update(app.config) # 请求处理 request_process = OsrRequestProcess() request_process.init_request_process(app=app) request_process.init_babel_locale_selector(babel=babel) # 错误处理 ErrorHandler(app) # Logger # Other log_udp = LogServerUDP() r = log_udp.init_app() if r: log_udp.log_server() weblog = WebLogger() weblog.init_app(app) if not os.path.exists(TEMP_STATIC_FOLDER): os.makedirs(TEMP_STATIC_FOLDER)
def push_url_to_db(app): """ 同步url到数据库 :param app: :return: """ now_time = time.time() for rule in app.url_map.iter_rules(): if rule.endpoint.startswith("api.") or rule.endpoint.startswith( "open_api."): type = "api" else: continue r = mdbs["sys"].dbs["sys_urls"].find_one( {"url": rule.rule.rstrip("/")}) if not r: # 不存在 mdbs["sys"].dbs["sys_urls"].insert_one({ "url": rule.rule.rstrip("/"), "methods": list(rule.methods), "endpoint": rule.endpoint, "custom_permission": {}, "type": type, "create": "auto", "update_time": now_time }) elif r: new_methods = list(rule.methods) if r["methods"]: new_methods.extend(r["methods"]) new_methods = list(set(new_methods)) mdbs["sys"].dbs["sys_urls"].update_one({"_id": r["_id"]}, { "$set": { "methods": new_methods, "endpoint": rule.endpoint, "type": type, "create": "auto", "update_time": now_time } }) urls = mdbs["sys"].dbs["sys_urls"].find({}) for url in urls: if "url" in url: cache.delete(key="get_sys_url_url_{}".format(url['url']), db_type="redis") # 清理已不存在的api mdbs["sys"].dbs["sys_urls"].delete_many({ "type": { "$ne": "page" }, "update_time": { "$lt": now_time } })
def import_plugin_config(plugin_name, config): """ 导入插件配置到数据库,已存在的则更新时间 :param plugin_name 插件名 :param CONFIG:dict :return: """ current_time = time.time() for k, v in config.items(): if "value_type" not in v: assert Exception( 'Plugin configuration import database error, missing "value_type"' ) if "reactivate" not in v: v["reactivate"] = True if "info" not in v: v["info"] = "" # 查找相同的配置 r = mdbs["sys"].db.plugin_config.find_one({ "plugin_name": plugin_name, "key": k, "value_type": v["value_type"] }) if not r: # 如果不存在 mdbs["sys"].db.plugin_config.insert_one({ "plugin_name": plugin_name, "key": k, "value_type": v["value_type"], "value": v["value"], "reactivate": v["reactivate"], "info": v["info"], "update_time": time.time() }) elif r and r["update_time"] < current_time: # 存在, 而且比当前时间前的(防止同时启动多个进程时错乱,导致下面程序当旧数据清理) mdbs["sys"].db.plugin_config.update_one( { "_id": r["_id"], "update_time": { "$lt": current_time } }, { "$set": { "update_time": current_time, "reactivate": v["reactivate"], "info": v["info"] } }) # 删除已不需要的配置 mdbs["sys"].db.plugin_config.delete_many({ "plugin_name": plugin_name, "update_time": { "$lt": current_time } }) # 更新插件配置缓存, # 删除缓存,达到更新缓存 cache.delete(key=PLUG_IN_CONFIG_CACHE_KEY)
def sys_config_edit(): key = request.argget.all('key') project = request.argget.all('project') value = request.argget.all('value') info = request.argget.all('info') version = mdb_sys.db.sys_config.find_one( {"new_version": { "$exists": True }}, {"_id": 0}) s, r = arg_verify(reqargs=[("key", key), ("project", project)], required=True) if not s: return r old_conf = mdb_sys.db.sys_config.find_one({ "key": key, "project": project, "conf_version": version["new_version"] }) if not old_conf: data = { "msg": gettext("There is no such data"), "msg_type": "e", "http_status": 404 } else: try: if old_conf["type"] == "int" or old_conf["type"] == "binary": value = int(value) elif old_conf["type"] == "float": value = float(value) elif old_conf["type"] == "string": value = str(value) elif old_conf["type"] == "bool": try: value = int(value) if value: value = True else: value = False except: pass if value or (isinstance(value, str) and value.upper() != "FALSE"): value = True else: value = False elif old_conf["type"] == "list": # 如果不是list类型,则转为list类型 if not isinstance(value, list): # "[]"转list value = json.loads(value) if not isinstance(value, list): # "aaa,bbb,ccc"转["aaa", "bbb", "ccc"] value = value.strip(",").split(",") value = [v.strip("\n") for v in value] elif old_conf["type"] == "dict": if not isinstance(value, dict): value = json.loads(value) if not isinstance(value, dict): data = { "msg": gettext( 'The format of the "value" errors, need a "{}" type' ).format(old_conf["type"]), "msg_type": "e", "http_status": 400 } return data elif old_conf["type"] == "tuple": if not isinstance(value, tuple): value = json.loads(value) if not isinstance(value, tuple): data = { "msg": gettext( 'The format of the "value" errors, need a "{}" type' ).format(old_conf["type"]), "msg_type": "e", "http_status": 400 } return data elif old_conf["type"] == "password": value = str(value) else: data = { "msg": gettext('There is no {}').format(old_conf["type"]), "msg_type": "e", "http_status": 400 } return data except Exception as e: data = { "msg": gettext('The format of the "value" errors, need a "{}" type'). format(old_conf["type"]), "msg_type": "e", "http_status": 400 } return data if not info: info = old_conf["info"] conf = {"value": value, "update_time": time.time(), "info": info} # 更新版本 # 解释:只要有一台服务器端重启web并更新配置, 则会把重启时最新版本加入到used_version中 if version["new_version"] in version["used_versions"]: # 如果目前的最新版本号在used_version中, 则本次修改就要生成更新的配置版本 now_version = time_to_utcdate(tformat="%Y_%m_%d_%H_%M_%S") old_version = mdb_sys.db.sys_config.find( { "project": { "$exists": True }, "conf_version": version["new_version"] }, {"_id": 0}) # 生成最新版本配置 for v in old_version: v["conf_version"] = now_version mdb_sys.db.sys_config.insert_one(v) # 更新当前使用的最新版本号 mdb_sys.db.sys_config.update_one( {"new_version": { "$exists": True }}, {"$set": { "new_version": now_version }}) # 删除多余的配置版本 ver_cnt = len(version["used_versions"]) if ver_cnt >= 15: rm_vers = version["used_versions"][0:ver_cnt - 15] mdb_sys.db.sys_config.update_one( {"new_version": { "$exists": True }}, { "$set": { "used_versions": version["used_versions"][ver_cnt - 15:] } }) mdb_sys.db.sys_config.delete_many( {"version": { "$in": rm_vers }}) else: # 否则, 本次修改暂不生成新配置版本 now_version = version["new_version"] # 更新修改数据 mdb_sys.db.sys_config.update_one( { "project": project, "key": key, "conf_version": now_version }, {"$set": conf}, upsert=True) # 删除缓存,达到更新缓存 cache.delete(CONFIG_CACHE_KEY) data = { "msg": gettext("Modify the success"), "msg_type": "s", "http_status": 201 } return data
def init_core_module(app): """ 初始化核心模块 :param app: :return: """ # app config web_start_log.info("Initialize the core module") # 系统必要配置, 优先导入 app.config.from_object(ConfDictToClass(CONFIG["system"], key="value")) app.config.from_object(ConfDictToClass(CONFIG["key"], key="value")) # 数据库 app.config.from_object(DatabaseConfig()) for name, mdb in mdbs.items(): mdb.init_app(app, config_prefix=name.upper()) # 缓存 app.config.from_object(ConfDictToClass(CONFIG["cache"], key="value")) app.config["CACHE_REDIS"] = redis app.config["CACHE_MONGODB"] = mdbs["sys"].connection app.config["CACHE_MONGODB_DB"] = mdbs["sys"].name cache.init_app(app) # 清除配置CONFIG的cache with app.app_context(): msg = " * Clean configuration cache successfully" cache.delete(CONFIG_CACHE_KEY) cache.delete(PLUG_IN_CONFIG_CACHE_KEY) web_start_log.info(msg) print(msg) # 异常错误信息 app.config["PRESERVE_CONTEXT_ON_EXCEPTION"] = PRESERVE_CONTEXT_ON_EXCEPTION ################################################### # 在此之前, 任何程序不能调用utils.get_config.py下的方法 ################################################### from apps.core.utils.get_config import get_configs, get_config from apps.core.flask.request import OsrRequestProcess from apps.core.flask.errorhandler import ErrorHandler from apps.core.blueprint import api, admin_view, theme_view, static_html_view, static, open_api from apps.core.flask.routing import RegexConverter from apps.core.flask.routing import push_url_to_db # 最大请求大小 app.config["MAX_CONTENT_LENGTH"] = get_config( "system", "MAX_CONTENT_LENGTH") * 1024 * 1024 # Session会话配置 session_config = get_configs("session") session_config["SESSION_PROTECTION"] = SESSION_PROTECTION session_config["SESSION_COOKIE_PATH"] = SESSION_COOKIE_PATH session_config["SESSION_COOKIE_HTTPONLY"] = SESSION_COOKIE_HTTPONLY session_config["SESSION_COOKIE_SECURE"] = SESSION_COOKIE_SECURE session_config["SESSION_USE_SIGNER"] = SESSION_USE_SIGNER session_config["SESSION_MONGODB_DB"] = mdbs["sys"].name app.config.from_object(ConfDictToClass(session_config)) app.config["SESSION_REDIS"] = redis app.config["SESSION_MONGODB"] = mdbs["sys"].connection sess.init_app(app) rest_session.init_app(app) # 邮件 app.config.from_object(ConfDictToClass(get_configs("email"))) mail.init_app(app) # Csrf token csrf_config = {} csrf_config["CSRF_ENABLED"] = CSRF_ENABLED csrf_config["WTF_CSRF_CHECK_DEFAULT"] = WTF_CSRF_CHECK_DEFAULT csrf_config["WTF_CSRF_METHODS"] = WTF_CSRF_METHODS app.config.from_object(ConfDictToClass(csrf_config)) csrf.init_app(app) # Babel app.config.from_object(ConfDictToClass(get_configs("babel"))) app.config["BABEL_TRANSLATION_DIRECTORIES"] = BABEL_TRANSLATION_DIRECTORIES babel.init_app(app) # 登录管理 login_manager.init_app(app) # login_manager.anonymous_user = AnonymousUser() login_manager.session_protection = SESSION_PROTECTION oauth.init_app(app) # 让路由支持正则 app.url_map.converters['regex'] = RegexConverter # 注册蓝图 blueprint web_start_log.info("Register blueprint, Initialize the routing") app.register_blueprint(api) app.register_blueprint(open_api) app.register_blueprint(admin_view) app.register_blueprint(theme_view) app.register_blueprint(static_html_view) app.register_blueprint(static) push_url_to_db(app) # 请求处理 request_process = OsrRequestProcess() request_process.init_request_process(app=app) request_process.init_babel_locale_selector(babel=babel) # 错误处理 ErrorHandler(app) # Logger # Other log_udp = LogServerUDP() r = log_udp.init_app() if r: log_udp.log_server() weblog = WebLogger() weblog.init_app(app)
def compatible_processing(mdbs, stage=1): """ 兼容上一个版本 :return: """ if stage == 1: # 当前主题设置加上主题名称 theme = mdbs["sys"].dbs["sys_config"].find_one({"project": "theme", "key": "CURRENT_THEME_NAME"}) if theme: theme_name = theme["value"] mdbs["sys"].dbs["theme_display_setting"].update_many({"theme_name": {"$exists": False}}, {"$set": {"theme_name": theme_name}}) # 主题设置的数据分类信息转移 categorys = mdbs["web"].db.category.find({"type": {"$regex": ".+_theme$"}}) for category in categorys: category["type"] = category["type"].replace("_theme", "") category["theme_name"] = theme_name r = mdbs["web"].db.theme_category.insert_one(category) if r.inserted_id: mdbs["web"].db.category.delete_one({"_id": category["_id"]}) ''' v2.0之后新功能: 兼容 2.0Beta, v2.0 ''' # 判断是第一次部署网站还是升级版本 its_not_first = mdbs["user"].dbs["permission"].find_one({}) if its_not_first and not mdbs["sys"].dbs["theme_nav_setting"].find_one({}): # 将导航设置迁移到主题导航设置专属模块数据库 r = mdbs["sys"].dbs["sys_config"].find( {"project": "theme_global_conf", "key": "TOP_NAV"} ).sort([("update_time", -1)]).limit(1) if r.count(True): for i, v in r[0]["value"].items(): display_name = v["nav"] updata = { "order": 1, "display_name": display_name, "theme_name": theme_name, "language": "zh_CN" } del v["nav"] updata["json_data"] = v mdbs["sys"].dbs["theme_nav_setting"].update_one( {"theme_name": theme_name, "display_name": display_name}, {"$set": updata}, upsert=True ) elif stage == 2: # 2020/1/23 version v2.2 # 更新最高权限 is_updated = False pers = mdbs["user"].dbs["permission"].find({}) cnt = pers.count(True) if cnt: pers = pers.sort([("value", -1)]) per = pers[0] root = 0b10000000000000000000000000000000000000000000000000000 if per["value"] < root: mdbs["user"].dbs["permission"].update_one( {"_id": per["_id"]}, {"$set": {"value": root}} ) is_updated = True if cnt > 1: per = pers[1] admin = 0b1000000000000000000000000000000000000000000000000000 if per["value"] < admin: mdbs["user"].dbs["permission"].update_one( {"_id": per["_id"]}, {"$set": {"value": admin}} ) is_updated = True # 更新root角色 roles = mdbs["user"].dbs["role"].find({}) if roles.count(True): role = roles.sort([("permissions", -1)])[0] if role["permissions"] < SUPER_PER: mdbs["user"].dbs["role"].update_one( {"_id": role["_id"]}, {"$set": {"permissions": SUPER_PER}} ) is_updated = True if is_updated: cache.delete(key=GET_DEFAULT_SYS_PER_CACHE_KEY, db_type="redis") cache.delete(key=GET_ALL_PERS_CACHE_KEY, db_type="redis") cache.delete(key=GET_ALL_PERS_CACHE_KEY, db_type="redis") cache.delete_autokey(fun=".*get_one_user.*", db_type="redis", key_regex=True)
def update_plugin_setting(): ''' 获取插件设置 :return: ''' plugin_name = request.argget.all('plugin_name') key = request.argget.all('key') value = request.argget.all('value') s, r = arg_verify(reqargs=[("plugin name", plugin_name), ("key", key)], required=True) if not s: return r old_conf = mdb_sys.db.plugin_config.find_one({ "key": key, "plugin_name": plugin_name }) if not old_conf: data = { "msg": gettext("There is no such data"), "msg_type": "e", "http_status": 404 } else: try: if old_conf["value_type"] == "int" or old_conf[ "value_type"] == "binary": value = int(value) elif old_conf["value_type"] == "float": value = float(value) elif old_conf["value_type"] == "string": value = str(value) elif old_conf["value_type"] == "bool": try: value = int(value) if value: value = True else: value = False except: pass if value or (isinstance(value, str) and value.upper() != "FALSE"): value = True else: value = False elif old_conf["value_type"] == "list": # 如果不是list类型,则转为list类型 if not isinstance(value, list): # "[]"转list value = json.loads(value) if not isinstance(value, list): # "aaa,bbb,ccc"转["aaa", "bbb", "ccc"] value = value.strip(",").split(",") value = [v.strip("\n") for v in value] elif old_conf["value_type"] == "dict": if not isinstance(value, dict): value = json.loads(value) if not isinstance(value, dict): data = { "msg": gettext( 'The format of the "value" errors, need a "{}" type' ).format(old_conf["value_type"]), "msg_type": "e", "http_status": 400 } return data elif old_conf["value_type"] == "tuple": if not isinstance(value, tuple): value = json.loads(value) if not isinstance(value, tuple): data = { "msg": gettext( 'The format of the "value" errors, need a "{}" type' ).format(old_conf["value_type"]), "msg_type": "e", "http_status": 400 } return data elif old_conf["value_type"] == "password": value = str(value) else: data = { "msg": gettext('There is no {}').format(old_conf["value_type"]), "msg_type": "e", "http_status": 400 } return data except Exception as e: data = { "msg": gettext('The format of the "value" errors, need a "{}" type'). format(old_conf["value_type"]), "msg_type": "e", "http_status": 400 } return data conf = {"value": value, "update_time": time.time()} # 更新修改数据 mdb_sys.db.plugin_config.update_one( { "plugin_name": plugin_name, "key": key }, {"$set": conf}, upsert=True) # 删除缓存,达到更新缓存 cache.delete(PLUG_IN_CONFIG_CACHE_KEY) data = { "msg": gettext("Modify the success"), "msg_type": "s", "http_status": 201 } return data
def switch_theme(): """ 切换主题 :return: """ theme_name = request.argget.all('theme_name') path = os.path.join(THEME_TEMPLATE_FOLDER, theme_name.strip()) if not os.path.exists(path): data = { "msg": gettext("Theme does not exist"), "msg_type": "e", "http_status": 400 } return data s, r = verify_theme(path, theme_name, theme_name) if s: # 更新主题数据 mdb_sys.db.sys_config.update_many( { "project": "theme", "key": "CURRENT_THEME_NAME" }, { "$set": { "value": theme_name.strip(), "update_time": time.time() } }, upsert=True) theme_info = get_one_theme_info(theme_name) if theme_info and "version" in theme_info: mdb_sys.db.sys_config.update_many( { "project": "theme", "key": "VERSION" }, { "$set": { "value": theme_info["version"], "update_time": time.time() } }, upsert=True) mdb_sys.db.sys_config.update_many( { "project": "site_config", "key": "STATIC_FILE_VERSION" }, { "$set": { "value": int(time_to_utcdate(time.time(), "%Y%m%d%H%M%S")), "update_time": time.time() } }, upsert=True) cache.delete(CONFIG_CACHE_KEY) data = { "msg": gettext("Switch success"), "msg_type": "s", "http_status": 201 } else: data = {"msg": r, "msg_type": "e", "http_status": 400} return data
def update_url(): ''' 更新修改 url权限 :return: ''' id = request.argget.all("id") method = request.argget.all("method") login_auth = str_to_num(request.argget.all("login_auth", 0)) custom_permission = json_to_pyseq( request.argget.all("custom_permission", [])) s, r = arg_verify([("id", id)], required=True) if not s: return r s, r = arg_verify( [(gettext("method"), method)], required=True, only=["GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS", "HEAD"]) if not s: return r permission = 0x0 for i in custom_permission: try: i = int(i) permission = permission | int(i) except: pass # 修改权限验证 data = { "msg": gettext( "The current user permissions are lower than the permissions you want to modify," " without permission to modify"), "msg_type": "w", "http_status": 401 } user_role = mdb_user.db.role.find_one( {"_id": ObjectId(current_user.role_id)}) # 如果当前用户的权限最高位 小于 要修改成的权重的最高位,是不可以的 if get_num_digits(user_role["permissions"]) <= get_num_digits(permission): return data old_permission = 0 old_url_per = mdb_sys.db.sys_urls.find_one({"_id": ObjectId(id)}) if old_url_per and method in old_url_per["custom_permission"]: old_permission = old_url_per["custom_permission"][method] # 如果当前用户的权限最高位 小于 要修改url请求的权限,也是不可以 if get_num_digits( user_role["permissions"]) <= get_num_digits(old_permission): return data r = mdb_sys.db.sys_urls.update_one({"_id": ObjectId(id)}, { "$set": { "custom_permission.{}".format(method): permission, "login_auth.{}".format(method): login_auth } }) if r.modified_count: # 清除缓存 r = mdb_sys.db.sys_urls.find_one({"_id": ObjectId(id)}) if r: cache.delete(key="get_sys_url_url_{}".format(r['url']), db_type="redis") data = { "msg": gettext("Modify the success"), "msg_type": "s", "http_status": 201 } else: data = { "msg": gettext("No modification"), "msg_type": "w", "http_status": 400 } return data
def add_per(): name = request.argget.all('name', '').strip() explain = request.argget.all('explain') default = int(request.argget.all('is_default', 0).strip()) position = str_to_num(request.argget.all('position', 0)) data = { 'msg': gettext("Add a success"), 'msg_type': "s", "custom_status": 201 } s, r = arg_verify(reqargs=[(gettext("name"), name), (gettext("position"), position)], required=True) if not s: return r hightest_pos = get_num_digits(SUPER_PER) permissions = int(math.pow(2, position - 1)) if hightest_pos > hightest_pos and position < 1: data = { 'msg': gettext("Must be an integer greater than 0," " less than or equal to {}".format(hightest_pos)), 'msg_type': "w", "custom_status": 403 } elif mdbs["user"].db.permission.find_one({"name": name}): data = { 'msg': gettext("Permission name or valready exists"), 'msg_type': "w", "custom_status": 403 } elif mdbs["user"].db.permission.find_one({"value": permissions}): data = { 'msg': gettext('Location has been used'), 'msg_type': "w", "custom_status": 403 } else: user_role = mdbs["user"].db.role.find_one( {"_id": ObjectId(current_user.role_id)}) if get_num_digits( user_role["permissions"]) <= get_num_digits(permissions): data = { "msg": gettext( "The current user permissions are lower than the permissions that you want to add," " without permission to add"), "msg_type": "w", "custom_status": 401 } return data mdbs["user"].db.permission.insert_one({ "name": name, "explain": explain, 'value': permissions, "is_default": default }) cache.delete(key=GET_DEFAULT_SYS_PER_CACHE_KEY, db_type="redis") cache.delete(key=GET_ALL_PERS_CACHE_KEY, db_type="redis") return data
def delete_per(): ids = json_to_pyseq(request.argget.all('ids')) user_role = mdbs["user"].db.role.find_one( {"_id": ObjectId(current_user.role_id)}) unauth_del_pers = [] # 无权删除的 preserve = [] # 必须保留的 need_remove = [] need_remove_per_value = [] for tid in ids: tid = ObjectId(tid) # 权限检查 old_per = mdbs["user"].db.permission.find_one({"_id": tid}) # 如果当前用户的权限最高位 小于 要删除角色的权限,也是不可以 if old_per and get_num_digits(old_per["value"]) >= get_num_digits( user_role["permissions"]): unauth_del_pers.append(old_per["name"]) continue if old_per["name"] in PRESERVE_PERS or old_per["default"]: preserve.append(old_per["name"]) continue need_remove.append(tid) need_remove_per_value.append(old_per["permissions"]) # Delete msg_updated_rolename = "" if need_remove: mdbs["user"].db.permission.delete_many({ "_id": { "$in": need_remove }, "name": { "$nin": PRESERVE_PERS } }) # 删除后必须更新使用了该权限的role和api&page updated_rolename = [] for v in need_remove_per_value: r = update_role_and_api_per(old_per_value=v, new_per_value=0) updated_rolename.extend(r["updated_rolename"]) msg_updated_rolename = gettext("The role of the chain reaction is: \n") if updated_rolename: updated_rolename = list(set(updated_rolename)) for ur in updated_rolename: msg_updated_rolename = '{}, "{}"'.format( msg_updated_rolename, ur) cache.delete(key=GET_DEFAULT_SYS_PER_CACHE_KEY, db_type="redis") cache.delete(key=GET_ALL_PERS_CACHE_KEY, db_type="redis") if not unauth_del_pers and not preserve: data = { 'msg': gettext('Successfully deleted. {}'.format(msg_updated_rolename)), 'msg_type': 'success', "custom_status": 204 } else: warning_msg = "" if unauth_del_pers: warning_msg = gettext('No permission to delete {}. ').format( ",".join(unauth_del_pers)) elif preserve: warning_msg = gettext( "{}{} are permissions that must be retained.").format( warning_msg, ",".join(preserve)) data = { 'msg': warning_msg, 'msg_type': 'warning', "custom_status": 400 } return data
def load_plugin(self, plugin_name, is_import=False): ''' 加载插件 import :param plugin_name: :return: ''' plug_path = os.path.join(self.plugin_path, plugin_name) s, r = verify_plugin(plug_path) if not s: # 标记插件为出错插件 mdb_sys.dbs["plugin"].update_one( { "plugin_name": plugin_name, "update_time": { "$lt": self.current_time } }, { "$set": { "error": r, "installed_time": self.current_time, "update_time": self.current_time, "active": 0, "require_package_install_result": [] } }, upsert=True) return s, r # 查看是否有需求文件 if os.path.exists(os.path.join(plug_path, "requirements.txt")): requirements_exist = True else: requirements_exist = False # 读取yaml配置 fpath = os.path.join(plug_path, "conf.yaml") with open(fpath) as rf: # 读取插件配置文件 plug_conf = yaml.load(rf) hook_name = plug_conf["hook_name"] module = None current_plug = mdb_sys.dbs["plugin"].find_one( {"plugin_name": plugin_name}) freed = False # 如果插件存在, 并标记为删除,那就删除插件文件 if current_plug and "is_deleted" in current_plug and current_plug[ "is_deleted"]: try: shutil.rmtree(plug_path) except: pass freed = True if is_import or (current_plug and current_plug["error"]): # 需要导入插件模块或者插件模块之前鉴定有错误 startup_file_name = plug_conf["startup_file_name"] plug_main_file_path = os.path.join(plug_path, startup_file_name) if os.path.exists(plug_main_file_path): module_path = "apps.{}.{}.{}".format( PLUG_IN_FOLDER_NAME, plugin_name, startup_file_name[:-3]) try: if module_path in sys.modules: # 如果之前已加载 module = reload(sys.modules[module_path]) else: module = import_module(module_path) except BaseException as e: # 标记插件为出错插件 mdb_sys.dbs["plugin"].update_one( { "plugin_name": plugin_name, "update_time": { "$lt": self.current_time } }, { "$set": { "error": str(e), "update_time": self.current_time, "active": 0, "requirements_exist": requirements_exist, "require_package_install_result": [] } }, upsert=True) return False, str(e) else: return False, "{} {}".format( gettext("Plugin startup file does not exist"), plug_main_file_path) # 需要更新的数据 plug_conf["plugin_name"] = plugin_name plug_conf["update_time"] = self.current_time plug_conf["error"] = 0 plug_conf["requirements_exist"] = requirements_exist # 检测当前插件安装情况 if current_plug: # 如果插件未激活 if not current_plug["active"]: freed = True if freed: # 释放实例对象 self.unregister_plugin(plugin_name) # 更新插件信息到数据库 mdb_sys.dbs["plugin"].update_one( { "plugin_name": plugin_name, "update_time": { "$lt": self.current_time } }, {"$set": plug_conf}) else: # 插件不存在 plug_conf["active"] = 0 plug_conf["is_deleted"] = 0 plug_conf["installed_time"] = self.current_time mdb_sys.dbs["plugin"].insert_one(plug_conf) # 清理遗留缓存 cache.delete(key="get_plugin_info_hook_name_{}".format(hook_name), db_type="redis") return True, { "module": module, "hook_name": hook_name, "plugin_name": plugin_name }
def push_url_to_db(app): """ 同步url到数据库 :param app: :return: """ # back up now_time = time.time() ud = time_to_utcdate(now_time, "%Y%m%d%H") days_ago_t = now_time - 86400 * 7 days_ago_d = time_to_utcdate(days_ago_t, "%Y%m%d%H") if not mdbs["sys"].dbs["sys_urls_back"].find_one({"backup_time": ud}): sys_urls = list(mdbs["sys"].dbs["sys_urls"].find({}, {"_id": 0})) for sys_url in sys_urls: sys_url["backup_time"] = ud mdbs["sys"].dbs["sys_urls_back"].insert(sys_urls) mdbs["sys"].dbs["sys_urls_back"].delete_many( {"backup_time": { "$lt": days_ago_d }}) for rule in app.url_map.iter_rules(): if rule.endpoint.startswith("api.") or rule.endpoint.startswith( "open_api."): type = "api" else: continue now_time = time.time() r = mdbs["sys"].dbs["sys_urls"].find_one( {"url": rule.rule.rstrip("/")}) if not r: # 不存在 mdbs["sys"].dbs["sys_urls"].insert_one({ "url": rule.rule.rstrip("/"), "methods": list(rule.methods), "endpoint": rule.endpoint, "custom_permission": {}, "type": type, "create": "auto", "update_time": now_time }) elif r: new_methods = list(rule.methods) if r["methods"]: new_methods.extend(r["methods"]) new_methods = list(set(new_methods)) mdbs["sys"].dbs["sys_urls"].update_one({"_id": r["_id"]}, { "$set": { "methods": new_methods, "endpoint": rule.endpoint, "type": type, "create": "auto", "update_time": now_time } }) urls = mdbs["sys"].dbs["sys_urls"].find({}) for url in urls: if "url" in url: cache.delete(key="get_sys_url_url_{}".format(url['url']), db_type="redis") """ # 清理已不存在的api # 时间7天是为了防止多台服务器同时启动时造成误删 """ ut = time.time() - 86400 * 7 mdbs["sys"].dbs["sys_urls"].delete_many({ "type": { "$ne": "page" }, "update_time": { "$lt": ut } })