def start_plugin(): """ 开启一个插件 :return: """ name = request.argget.all('name') s, r = arg_verify(reqargs=[(gettext("name"), name)], required=True) if not s: return r find_query = {"plugin_name": name, "error": {"$in": [0, False]}} plugin = mdbs["sys"].db.plugin.find_one(find_query) if plugin: other_plugin = mdbs["sys"].db.plugin.find_one({ "hook_name": plugin["hook_name"], "active": { "$in": [1, True] } }) if other_plugin: data = { "msg": gettext("Plugin[{}] with similar functionality is in use," " please stop it first").format( other_plugin["plugin_name"]), "msg_type": "w", "custom_status": 400 } return data r = mdbs["sys"].db.plugin.update_one(find_query, {"$set": {"active": 1}}) register_r = plugin_manager.register_plugin(name) if r.modified_count and register_r: # 清除缓存 r = mdbs["sys"].db.plugin.find_one({"plugin_name": name}) if r: cache.delete_autokey(fun="get_plugin_info", db_type="redis", hook_name=r['hook_name']) data = { "msg": gettext("Plug-in activated successfully"), "msg_type": "s", "custom_status": 201 } elif r.matched_count and register_r: data = { "msg": gettext("Plug-in is already activated"), "msg_type": "w", "custom_status": 400 } else: data = { "msg": gettext("Plug-in activation failed"), "msg_type": "w", "custom_status": 400 } return data
def del_navs(): ids = json_to_pyseq(request.argget.all("ids")) s, r = arg_verify([(gettext("ids"), ids)], required=True) if not s: return r del_ids = [] for id in ids: del_ids.append(ObjectId(id)) r = mdbs["sys"].dbs["theme_nav_setting"].delete_many( {"_id": { "$in": del_ids }}) if r.deleted_count: data = { "msg": gettext("Deleted successfully"), "msg_type": "s", "custom_status": 200 } else: data = { "msg": gettext("Delete failed"), "msg_type": "s", "custom_status": 200 } cache.delete_autokey(fun="get_global_theme_navs", theme_name=".*", lang=".*", db_type="redis", key_regex=True) return data
def stop_plugin(): """ 停用一个插件 :return: """ name = request.argget.all('name') s, r = arg_verify(reqargs=[(gettext("name"), name)], required=True) if not s: return r r = mdbs["sys"].db.plugin.update_one({"plugin_name": name}, {"$set": { "active": 0 }}) if r.matched_count: # 清除缓存 r = mdbs["sys"].db.plugin.find_one({"plugin_name": name}) if r: cache.delete_autokey(fun="get_plugin_info", db_type="redis", hook_name=r['hook_name']) data = { "msg": gettext("Plug-in stopped successfully"), "msg_type": "s", "custom_status": 201 } else: data = { "msg": gettext("Plug-in failed to stop"), "msg_type": "w", "custom_status": 400 } return data
def delete_url(): """ 删除url, 值允许删除页面路由 :return: """ ids = json_to_pyseq(request.argget.all("ids", [])) for i, tid in enumerate(ids): ids[i] = ObjectId(tid) url_pers = list(mdbs["sys"].db.sys_urls.find( {"_id": {"$in": ids}}, {"url": 1})) r = mdbs["sys"].db.sys_urls.delete_many( {"_id": {"$in": ids}, "create": "manual"}) if r.deleted_count: # 清除缓存 for url_per in url_pers: cache.delete_autokey( fun="get_sys_url", db_type="redis", url=url_per['url'].rstrip("/")) data = { "msg": gettext("Successfully deleted"), "msg_type": "s", "custom_status": 204} else: data = { "msg": gettext("Delete failed"), "msg_type": "w", "custom_status": 400} return data
def delete_user_info_cache(user_id): """ 清理user缓存 :param user_id: :return: """ # 清理user信息数据缓存 cache.delete_autokey(fun="get_user_public_info", user_id=user_id, db_type="mongodb", key_regex=True) cache.delete_autokey(fun="get_user_all_info", user_id=user_id, db_type="mongodb", key_regex=True)
def insert_one_user(updata): ''' 插入一条数据 :param updata: :return: ''' r = mdb_user.db.user.insert_one(updata) fun_name = "get_one_user" cache.delete_autokey(fun=fun_name, db_type="redis", username=updata["username"]) cache.delete_autokey(fun=fun_name, db_type="redis", email=updata["email"]) return r
def update_role_and_api_per(old_per_value, new_per_value=0): """ 更新所有使用了old_per的role和api :param old_per: :param new_per: :return: """ # 更新使用了该权限的role # 当前所有的用户角色 updated_rolename = [] roles = mdbs["user"].db.role.find() for role in roles: if role["permissions"] & old_per_value and not ( role["permissions"] & get_permission("ROOT")): role_new_per = (role["permissions"] - old_per_value) | new_per_value mdbs["user"].db.role.update_many( {"_id": role["_id"]}, {"$set": { "permissions": role_new_per }}) updated_rolename.append(role["name"]) # 更新使用了该权限的url or page # 当前所有自定义权限url urls = list(mdbs["sys"].db.sys_urls.find( {"custom_permission": { "$ne": {}, "$exists": True }})) for url in urls: for method, v in url["custom_permission"].items(): if v & old_per_value: # 修改 url["custom_permission"][method] = ( v - old_per_value) | new_per_value # 更新 mdbs["sys"].db.sys_urls.update_one( {"_id": url["_id"]}, {"$set": { "custom_permission": url["custom_permission"] }}) cache.delete_autokey(fun="get_sys_url", db_type="redis", url=url['url'].rstrip("/")) return {"updated_rolename": updated_rolename}
def delete_plugin(): """ 删除一个插件 :return: """ name = request.argget.all('name') s, r = arg_verify(reqargs=[(gettext("name"), name)], required=True) if not s: return r # 清除缓存 plug = mdbs["sys"].db.plugin.find_one({"plugin_name": name}) r = mdbs["sys"].db.plugin.update_one( { "plugin_name": name, "active": { "$ne": 1 } }, {"$set": { "is_deleted": 1 }}) if r.modified_count or r.matched_count: data = { "msg": gettext("Successfully deleted"), "msg_type": "s", "custom_status": 204 } # 删除配置 mdbs["sys"].db.plugin_config.delete_many({"plugin_name": name}) # 删除缓存,达到更新缓存 cache.delete(PLUG_IN_CONFIG_CACHE_KEY) cache.delete_autokey(fun="get_plugin_info", db_type="redis", hook_name=plug['hook_name']) else: data = { "msg": gettext("Failed to delete"), "msg_type": "w", "custom_status": 400 } return data
def clean_get_one_user_cache(user_id=None, user=None): ''' 清理get_one_user的cache :param user: :return: ''' fun_name = "get_one_user" if user_id and not user: user = mdb_user.db.user.find_one({"_id": ObjectId(user_id)}) if user: cache.delete_autokey(fun=fun_name, db_type="redis", user_id=str(user["_id"])) cache.delete_autokey(fun=fun_name, db_type="redis", username=user["username"]) cache.delete_autokey(fun=fun_name, db_type="redis", email=user["email"])
def nav_setting(): """ Update :RETURN: """ cid = request.argget.all("id") theme_name = request.argget.all("theme_name") lang = request.argget.all("language") display_name = request.argget.all("display_name") order = str_to_num(request.argget.all("order", 99)) json_data = json_to_pyseq(request.argget.all("json_data")) s, r = arg_verify([(gettext("Display name"), display_name), (gettext("theme name"), theme_name), (gettext("language"), lang), (gettext("Json data"), json_data)], required=True) if not s: return r if not isinstance(json_data, dict): data = { "msg": gettext('Value must be of type json'), "msg_type": "e", "custom_status": 400 } return data if not cid: updata = { 'theme_name': theme_name, 'display_name': display_name, 'language': lang, 'json_data': json_data, "order": order } r = mdbs["sys"].dbs["theme_nav_setting"].insert_one(updata) if r.inserted_id: data = { "msg": gettext("Navigation added successfully"), "msg_type": "s", "custom_status": 200 } else: data = { "msg": gettext("Failed to add navigation"), "msg_type": "w", "custom_status": 400 } else: updata = { 'theme_name': theme_name, 'display_name': display_name, 'language': lang, 'json_data': json_data, "order": order } r = mdbs["sys"].dbs["theme_nav_setting"].update_one( {"_id": ObjectId(cid)}, {"$set": updata}) if r.modified_count: data = { "msg": gettext("Updated successfully"), "msg_type": "s", "custom_status": 200 } elif r.matched_count: data = { "msg": gettext("Unmodified"), "msg_type": "w", "custom_status": 200 } else: data = { "msg": gettext("Update failed"), "msg_type": "w", "custom_status": 400 } cache.delete_autokey(fun="get_global_theme_navs", theme_name=".*", lang=".*", db_type="redis", key_regex=True) return data
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 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: # 标记插件为出错插件 mdbs["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 = mdbs["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 BaseException: 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: # 标记插件为出错插件 mdbs["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) # 更新插件信息到数据库 mdbs["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 mdbs["sys"].dbs["plugin"].insert_one(plug_conf) # 清理遗留缓存 cache.delete_autokey(fun="get_plugin_info", db_type="redis", hook_name=hook_name) 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) old_methods = r["methods"] if old_methods: new_methods.extend(old_methods) else: old_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 } }) new_methods.sort() old_methods.sort() if new_methods != old_methods or rule.endpoint != r["endpoint"]: # 清理缓存 cache.delete_autokey(fun="get_sys_url", key_base64=False, db_type="redis", url=r["url"]) """ # 清理已不存在的api # 时间7天是为了防止多台服务器同时启动时造成误删 """ ut = time.time() - 86400 * 7 mdbs["sys"].dbs["sys_urls"].delete_many({ "type": { "$ne": "page" }, "update_time": { "$lt": ut } })
def update_url(): """ 更新修改 url权限 :return: """ tid = 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", tid)], 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 BaseException: pass # 修改权限验证 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)}) # 如果当前用户的权限最高位 小于 要修改成的权重的最高位,是不可以的 if get_num_digits(user_role["permissions"]) <= get_num_digits(permission): return data old_permission = 0 old_url_per = mdbs["sys"].db.sys_urls.find_one({"_id": ObjectId(tid)}) 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 = mdbs["sys"].db.sys_urls.update_one({"_id": ObjectId(tid)}, { "$set": { "custom_permission.{}".format(method): permission, "login_auth.{}".format(method): login_auth } }) if r.modified_count: # 清除缓存 r = mdbs["sys"].db.sys_urls.find_one({"_id": ObjectId(tid)}) if r: cache.delete_autokey(fun="get_sys_url", db_type="redis", url=r['url'].rstrip("/")) data = { "msg": gettext("Modify the success"), "msg_type": "s", "custom_status": 201 } else: data = { "msg": gettext("No modification"), "msg_type": "w", "custom_status": 400 } return data