From 7f7e142dc412ff3a66c60dead3b2036bafe0ee96 Mon Sep 17 00:00:00 2001 From: wojiaoyishang <422880152@qq.com> Date: Sat, 11 Feb 2023 08:28:23 +0800 Subject: [PATCH 01/21] =?UTF-8?q?=E5=8E=BB=E9=99=A4=E6=8F=92=E5=BC=80?= =?UTF-8?q?=E5=8F=91=E8=80=85=E4=BF=A1=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- applications/dev/__init__.py | 1 + applications/dev/setting.py | 43 ++++++++++++++++++++++++++ applications/models/__init__.py | 1 + applications/models/plugin_setting.py | 10 ++++++ applications/schemas/__init__.py | 1 + applications/schemas/plugin_setting.py | 11 +++++++ applications/view/plugin/__init__.py | 4 --- pear.sql | 11 +++++++ plugins/helloworld/__init__.json | 6 +--- plugins/realip/__init__.json | 6 +--- plugins/replacePage/__init__.json | 6 +--- templates/admin/plugin/main.html | 4 --- 12 files changed, 81 insertions(+), 23 deletions(-) create mode 100644 applications/dev/setting.py create mode 100644 applications/models/plugin_setting.py create mode 100644 applications/schemas/plugin_setting.py diff --git a/applications/dev/__init__.py b/applications/dev/__init__.py index 4819129..58d9179 100644 --- a/applications/dev/__init__.py +++ b/applications/dev/__init__.py @@ -3,6 +3,7 @@ from applications.dev import role from applications.dev import power from applications.dev import department from applications.dev import console +from applications.dev import setting from flask import Flask # 获取app应用实例,会被初始化插件时重新赋值 diff --git a/applications/dev/setting.py b/applications/dev/setting.py new file mode 100644 index 0000000..84bbd22 --- /dev/null +++ b/applications/dev/setting.py @@ -0,0 +1,43 @@ +from applications.common import curd +from applications.models import pluginSetting +from applications.schemas import pluginSettingOutSchema +from applications.extensions import db + +def get(key): + """ + 获取设置数据库中保存的值。 + + :param key: 查询的键(最长长度 255) + + :return: value + """ + query = pluginSetting.query.filter_by(key=key).all() + data = curd.model_to_dicts(schema=pluginSettingOutSchema, data=query) + if len(data) == 0: + return None + return data[0]['value'] + +def set(key, value): + """ + 设置数据库的值。 + + :param key: 设置的键(最长长度 255) + :param value: 设置的值(最长长度 65525) + + :return: bool + """ + if len(pluginSetting.query.filter_by(key=key).all()) != 0: + d = pluginSetting.query.filter_by(key=key).update({"value": value}) + if d: + db.session.commit() + return True + else: + setting = pluginSetting( + key=key, + value=value + ) + r = db.session.add(setting) + db.session.commit() + return True + return False + \ No newline at end of file diff --git a/applications/models/__init__.py b/applications/models/__init__.py index d94b265..e4b8d98 100644 --- a/applications/models/__init__.py +++ b/applications/models/__init__.py @@ -8,3 +8,4 @@ from .admin_role_power import role_power from .admin_user import User from .admin_user_role import user_role from .admin_mail import Mail +from .plugin_setting import pluginSetting diff --git a/applications/models/plugin_setting.py b/applications/models/plugin_setting.py new file mode 100644 index 0000000..83f56c1 --- /dev/null +++ b/applications/models/plugin_setting.py @@ -0,0 +1,10 @@ +from applications.extensions import db + + +class pluginSetting(db.Model): + __tablename__ = 'plugin_setting' + id = db.Column(db.Integer, primary_key=True, autoincrement=True, comment="设置项ID") + key = db.Column(db.String(255), comment="设置键") + value = db.Column(db.String(65535), comment="设置值") + + \ No newline at end of file diff --git a/applications/schemas/__init__.py b/applications/schemas/__init__.py index 56a8678..cf9daa3 100644 --- a/applications/schemas/__init__.py +++ b/applications/schemas/__init__.py @@ -6,3 +6,4 @@ from .admin_dept import DeptOutSchema from .admin_log import LogOutSchema from .admin_photo import PhotoOutSchema from .admin_mail import MailOutSchema +from .plugin_setting import pluginSettingOutSchema diff --git a/applications/schemas/plugin_setting.py b/applications/schemas/plugin_setting.py new file mode 100644 index 0000000..68f2c3e --- /dev/null +++ b/applications/schemas/plugin_setting.py @@ -0,0 +1,11 @@ +from applications.extensions import ma +from marshmallow import fields, validate + + +class pluginSettingInSchema(ma.Schema): + key = fields.Str(required=True) + value = fields.Str(required=True) + +class pluginSettingOutSchema(ma.Schema): + key = fields.Str(attribute="key") + value = fields.Str(rattribute="value") diff --git a/applications/view/plugin/__init__.py b/applications/view/plugin/__init__.py index 2aa2d47..22ce27a 100644 --- a/applications/view/plugin/__init__.py +++ b/applications/view/plugin/__init__.py @@ -71,10 +71,6 @@ def data(): "plugin_name": info["plugin_name"], "plugin_version": info["plugin_version"], "plugin_description": info["plugin_description"], - "developer_name": info["developer_name"], - "developer_website": info["developer_website"], - "developer_email": info["developer_email"], - "developer_phone": info["developer_phone"], "plugin_folder_name": filename, "enable": "1" if filename in PLUGIN_ENABLE_FOLDERS else "0" } diff --git a/pear.sql b/pear.sql index e33d78a..6a5b12b 100644 --- a/pear.sql +++ b/pear.sql @@ -370,3 +370,14 @@ CREATE TABLE `alembic_version` ( INSERT INTO `alembic_version` VALUES ('7634e028e338'); SET FOREIGN_KEY_CHECKS = 1; + +-- ---------------------------- +-- Table structure for plugin_setting +-- ---------------------------- +DROP TABLE IF EXISTS `admin_user_role`; +CREATE TABLE `admin_user_role` ( + `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '标识', + `key` mediumtext COLLATE utf8_unicode_ci COMMENT '键', + `value` mediumtext COLLATE utf8_unicode_ci COMMENT '值', + PRIMARY KEY (`id`) +) ENGINE=MyISAM AUTO_INCREMENT=3 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; \ No newline at end of file diff --git a/plugins/helloworld/__init__.json b/plugins/helloworld/__init__.json index 110f9f7..1373e2d 100644 --- a/plugins/helloworld/__init__.json +++ b/plugins/helloworld/__init__.json @@ -1,9 +1,5 @@ { "plugin_name": "Hello World", "plugin_version": "1.0.0.1", - "plugin_description": "一个测试的插件。", - "developer_name": "Yishang", - "developer_website": "https://lovepikachu.top", - "developer_email": "422880152@qq.com", - "developer_phone": "-" + "plugin_description": "一个测试的插件。" } \ No newline at end of file diff --git a/plugins/realip/__init__.json b/plugins/realip/__init__.json index 2f7e77f..659ed4f 100644 --- a/plugins/realip/__init__.json +++ b/plugins/realip/__init__.json @@ -1,9 +1,5 @@ { "plugin_name": "真实IP插件", "plugin_version": "1.0.0.1", - "plugin_description": "在上游更改访客IP地址,并采用自定义日志输出。", - "developer_name": "Yishang", - "developer_website": "https://lovepikachu.top", - "developer_email": "422880152@qq.com", - "developer_phone": "-" + "plugin_description": "在上游更改访客IP地址,并采用自定义日志输出。" } \ No newline at end of file diff --git a/plugins/replacePage/__init__.json b/plugins/replacePage/__init__.json index d555882..143dd0c 100644 --- a/plugins/replacePage/__init__.json +++ b/plugins/replacePage/__init__.json @@ -1,9 +1,5 @@ { "plugin_name": "页面替换插件", "plugin_version": "1.0.0.1", - "plugin_description": "在不更改原有框架视图函数的情况下更改渲染输出页面。", - "developer_name": "Yishang", - "developer_website": "https://lovepikachu.top", - "developer_email": "422880152@qq.com", - "developer_phone": "-" + "plugin_description": "在不更改原有框架视图函数的情况下更改渲染输出页面。" } \ No newline at end of file diff --git a/templates/admin/plugin/main.html b/templates/admin/plugin/main.html index 4ba7465..b0e4f18 100644 --- a/templates/admin/plugin/main.html +++ b/templates/admin/plugin/main.html @@ -133,10 +133,6 @@ {field: 'plugin_name', minWidth: 100, title: '插件名称'}, {field: 'plugin_version', title: '插件版本'}, {field: 'plugin_description', title: '插件描述'}, - {field: 'developer_name', title: '开发者名称'}, - {field: 'developer_website', title: '开发者网站'}, - {field: 'developer_email', title: '开发者邮箱'}, - {field: 'developer_phone', title: '开发者电话'}, {field: 'plugin_folder_name', hide: true}, {field: 'enable', title: '状态', templet: '#plugin-enable', width: 100, align: 'center'}, {title: '操作', templet: '#plugin-bar', width: 120, align: 'center'} -- Gitee From 5b8c441b8b6c02db0826975606fd57b8324f701e Mon Sep 17 00:00:00 2001 From: wojiaoyishang <422880152@qq.com> Date: Sat, 11 Feb 2023 08:43:48 +0800 Subject: [PATCH 02/21] =?UTF-8?q?=E5=8E=BB=E9=99=A4=E6=8F=92=E5=BC=80?= =?UTF-8?q?=E5=8F=91=E8=80=85=E4=BF=A1=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pear.sql | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pear.sql b/pear.sql index 6a5b12b..50c93e6 100644 --- a/pear.sql +++ b/pear.sql @@ -374,10 +374,10 @@ SET FOREIGN_KEY_CHECKS = 1; -- ---------------------------- -- Table structure for plugin_setting -- ---------------------------- -DROP TABLE IF EXISTS `admin_user_role`; -CREATE TABLE `admin_user_role` ( +DROP TABLE IF EXISTS `plugin_setting`; +CREATE TABLE `plugin_setting` ( `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '标识', `key` mediumtext COLLATE utf8_unicode_ci COMMENT '键', `value` mediumtext COLLATE utf8_unicode_ci COMMENT '值', PRIMARY KEY (`id`) -) ENGINE=MyISAM AUTO_INCREMENT=3 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; \ No newline at end of file +) ENGINE = InnoDB AUTO_INCREMENT = 25 CHARACTER SET = utf8 COLLATE = utf8_unicode_ci ROW_FORMAT = DYNAMIC; -- Gitee From 0ad00448d85a0ddca1b7c80f566d8d7c47ba6855 Mon Sep 17 00:00:00 2001 From: wojiaoyishang <422880152@qq.com> Date: Sat, 11 Feb 2023 12:37:16 +0800 Subject: [PATCH 03/21] =?UTF-8?q?=E7=A7=BB=E9=99=A4=E8=A1=A8plugin=5Fsetti?= =?UTF-8?q?ng?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- applications/common/utils/rights.py | 7 +++++ applications/dev/__init__.py | 1 - applications/dev/setting.py | 43 -------------------------- applications/models/__init__.py | 1 - applications/models/plugin_setting.py | 10 ------ applications/schemas/__init__.py | 1 - applications/schemas/plugin_setting.py | 11 ------- pear.sql | 11 ------- 8 files changed, 7 insertions(+), 78 deletions(-) delete mode 100644 applications/dev/setting.py delete mode 100644 applications/models/plugin_setting.py delete mode 100644 applications/schemas/plugin_setting.py diff --git a/applications/common/utils/rights.py b/applications/common/utils/rights.py index 655593f..5ae9e31 100644 --- a/applications/common/utils/rights.py +++ b/applications/common/utils/rights.py @@ -5,6 +5,13 @@ from applications.common.admin_log import admin_log def authorize(power: str, log: bool = False): + """用户权限判断,用于判断目前会话用户是否拥有访问权限 + + :param power: 权限标识 + :type power: str + :param log: 是否记录日志, defaults to False + :type log: bool, optional + """ def decorator(func): @login_required @wraps(func) diff --git a/applications/dev/__init__.py b/applications/dev/__init__.py index 58d9179..4819129 100644 --- a/applications/dev/__init__.py +++ b/applications/dev/__init__.py @@ -3,7 +3,6 @@ from applications.dev import role from applications.dev import power from applications.dev import department from applications.dev import console -from applications.dev import setting from flask import Flask # 获取app应用实例,会被初始化插件时重新赋值 diff --git a/applications/dev/setting.py b/applications/dev/setting.py deleted file mode 100644 index 84bbd22..0000000 --- a/applications/dev/setting.py +++ /dev/null @@ -1,43 +0,0 @@ -from applications.common import curd -from applications.models import pluginSetting -from applications.schemas import pluginSettingOutSchema -from applications.extensions import db - -def get(key): - """ - 获取设置数据库中保存的值。 - - :param key: 查询的键(最长长度 255) - - :return: value - """ - query = pluginSetting.query.filter_by(key=key).all() - data = curd.model_to_dicts(schema=pluginSettingOutSchema, data=query) - if len(data) == 0: - return None - return data[0]['value'] - -def set(key, value): - """ - 设置数据库的值。 - - :param key: 设置的键(最长长度 255) - :param value: 设置的值(最长长度 65525) - - :return: bool - """ - if len(pluginSetting.query.filter_by(key=key).all()) != 0: - d = pluginSetting.query.filter_by(key=key).update({"value": value}) - if d: - db.session.commit() - return True - else: - setting = pluginSetting( - key=key, - value=value - ) - r = db.session.add(setting) - db.session.commit() - return True - return False - \ No newline at end of file diff --git a/applications/models/__init__.py b/applications/models/__init__.py index e4b8d98..d94b265 100644 --- a/applications/models/__init__.py +++ b/applications/models/__init__.py @@ -8,4 +8,3 @@ from .admin_role_power import role_power from .admin_user import User from .admin_user_role import user_role from .admin_mail import Mail -from .plugin_setting import pluginSetting diff --git a/applications/models/plugin_setting.py b/applications/models/plugin_setting.py deleted file mode 100644 index 83f56c1..0000000 --- a/applications/models/plugin_setting.py +++ /dev/null @@ -1,10 +0,0 @@ -from applications.extensions import db - - -class pluginSetting(db.Model): - __tablename__ = 'plugin_setting' - id = db.Column(db.Integer, primary_key=True, autoincrement=True, comment="设置项ID") - key = db.Column(db.String(255), comment="设置键") - value = db.Column(db.String(65535), comment="设置值") - - \ No newline at end of file diff --git a/applications/schemas/__init__.py b/applications/schemas/__init__.py index cf9daa3..56a8678 100644 --- a/applications/schemas/__init__.py +++ b/applications/schemas/__init__.py @@ -6,4 +6,3 @@ from .admin_dept import DeptOutSchema from .admin_log import LogOutSchema from .admin_photo import PhotoOutSchema from .admin_mail import MailOutSchema -from .plugin_setting import pluginSettingOutSchema diff --git a/applications/schemas/plugin_setting.py b/applications/schemas/plugin_setting.py deleted file mode 100644 index 68f2c3e..0000000 --- a/applications/schemas/plugin_setting.py +++ /dev/null @@ -1,11 +0,0 @@ -from applications.extensions import ma -from marshmallow import fields, validate - - -class pluginSettingInSchema(ma.Schema): - key = fields.Str(required=True) - value = fields.Str(required=True) - -class pluginSettingOutSchema(ma.Schema): - key = fields.Str(attribute="key") - value = fields.Str(rattribute="value") diff --git a/pear.sql b/pear.sql index 50c93e6..e33d78a 100644 --- a/pear.sql +++ b/pear.sql @@ -370,14 +370,3 @@ CREATE TABLE `alembic_version` ( INSERT INTO `alembic_version` VALUES ('7634e028e338'); SET FOREIGN_KEY_CHECKS = 1; - --- ---------------------------- --- Table structure for plugin_setting --- ---------------------------- -DROP TABLE IF EXISTS `plugin_setting`; -CREATE TABLE `plugin_setting` ( - `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '标识', - `key` mediumtext COLLATE utf8_unicode_ci COMMENT '键', - `value` mediumtext COLLATE utf8_unicode_ci COMMENT '值', - PRIMARY KEY (`id`) -) ENGINE = InnoDB AUTO_INCREMENT = 25 CHARACTER SET = utf8 COLLATE = utf8_unicode_ci ROW_FORMAT = DYNAMIC; -- Gitee From 67b1462453d3e20354f7e88a9183c2253f9085fb Mon Sep 17 00:00:00 2001 From: wojiaoyishang <422880152@qq.com> Date: Sat, 11 Feb 2023 13:34:46 +0800 Subject: [PATCH 04/21] =?UTF-8?q?dev=E6=96=87=E4=BB=B6=E5=A4=B9=E5=90=88?= =?UTF-8?q?=E5=B9=B6=E8=87=B3utils?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- applications/common/curd.py | 2 + applications/common/utils/__init__.py | 15 ++++ applications/{dev => common/utils}/console.py | 0 .../{dev => common/utils}/department.py | 0 applications/common/utils/mail.py | 86 +++++++++++++++++-- applications/{dev => common/utils}/power.py | 0 applications/{dev => common/utils}/role.py | 0 applications/{dev => common/utils}/user.py | 0 applications/common/utils/validate.py | 10 ++- applications/dev/__init__.py | 9 -- applications/dev/mail.py | 83 ------------------ applications/view/plugin/__init__.py | 4 +- plugins/helloworld/main.py | 2 - plugins/realip/__init__.py | 2 +- plugins/replacePage/__init__.py | 2 - 15 files changed, 107 insertions(+), 108 deletions(-) rename applications/{dev => common/utils}/console.py (100%) rename applications/{dev => common/utils}/department.py (100%) rename applications/{dev => common/utils}/power.py (100%) rename applications/{dev => common/utils}/role.py (100%) rename applications/{dev => common/utils}/user.py (100%) delete mode 100644 applications/dev/__init__.py delete mode 100644 applications/dev/mail.py diff --git a/applications/common/curd.py b/applications/common/curd.py index 9a4f16c..097a1dd 100644 --- a/applications/common/curd.py +++ b/applications/common/curd.py @@ -44,6 +44,8 @@ def auto_model_jsonify(data, model: db.Model): def model_to_dicts(schema: ma.Schema, data): """ + 将模型查询的数据对象转化为字典 + :param schema: schema类 :param model: sqlalchemy查询结果 :return: 返回单个查询结果 diff --git a/applications/common/utils/__init__.py b/applications/common/utils/__init__.py index e69de29..589ddd8 100644 --- a/applications/common/utils/__init__.py +++ b/applications/common/utils/__init__.py @@ -0,0 +1,15 @@ +from . import user +from . import role +from . import power +from . import department +from . import console +from . import gen_captcha +from . import http +from . import mail +from . import rights +from . import upload +from . import validate +from flask import Flask + +# 获取app应用实例,会被初始化插件时重新赋值 +app = None # type: Flask diff --git a/applications/dev/console.py b/applications/common/utils/console.py similarity index 100% rename from applications/dev/console.py rename to applications/common/utils/console.py diff --git a/applications/dev/department.py b/applications/common/utils/department.py similarity index 100% rename from applications/dev/department.py rename to applications/common/utils/department.py diff --git a/applications/common/utils/mail.py b/applications/common/utils/mail.py index eddc666..8c73474 100644 --- a/applications/common/utils/mail.py +++ b/applications/common/utils/mail.py @@ -1,13 +1,83 @@ +""" +集成了对 Pear Admin Flask 二次开发的的邮件操作,并给了相对应的示例。 +""" +from flask import current_app from flask_mail import Message -from applications.extensions.init_mail import mail +from applications.common.curd import model_to_dicts +from applications.common.helper import ModelFilter +from applications.extensions import db, flask_mail +from applications.models import Mail +from applications.schemas import MailOutSchema -# send_mail(subject='title', recipients=['123@qq.com'], content='body') -def send_mail(subject, recipients, content): +def get_all(receiver=None, subject=None, content=None): + """ + 获取邮件 + + 返回的列表中的字典构造如下:: + + { + "content": "", # html内容 + "create_at": "2022-12-25T10:51:17", # 时间 + "id": 17, # 邮件ID + "realname": "超级管理", # 创建者 + "receiver": "", # 接收者 + "subject": "" # 主题 + } + + :param receiver: 发送者 + :param subject: 邮件标题 + :param content: 邮件内容 + :return: 列表 + """ + # 查询参数构造 + mf = ModelFilter() + if receiver: + mf.contains(field_name="receiver", value=receiver) + if subject: + mf.contains(field_name="subject", value=subject) + if content: + mf.exact(field_name="content", value=content) + # orm查询 + # 使用分页获取data需要.items + mail = Mail.query.filter(mf.get_filter(Mail)).layui_paginate() + return model_to_dicts(schema=MailOutSchema, data=mail.items) + + +def add(receiver, subject, content, user_id): + """ + 发送一封邮件,若发送成功立刻提交数据库。 + + :param receiver: 接收者 多个用英文逗号隔开 + :param subject: 邮件主题 + :param content: 邮件 html + :param user_id: 发送用户ID(谁发送的?) 可以用 from flask_login import current_user ; current_user.id 来表示当前登录用户 + :return: 成功与否 + """ try: - message = Message(subject=subject, recipients=recipients, body=content) - mail.send(message) - except Exception as e: - print('邮箱发送出错了') - raise + msg = Message(subject=subject, recipients=receiver.split(";"), html=content) + flask_mail.send(msg) + except BaseException as e: + current_app.log_exception(e) + return False + + mail = Mail(receiver=receiver, subject=subject, content=content, user_id=user_id) + + db.session.add(mail) + db.session.commit() + return True + + +def delete(id): + """ + 删除邮件记录,立刻写入数据库。 + + :param id: 邮件ID + :return: 成功与否 + """ + res = Mail.query.filter_by(id=id).delete() + if not res: + return False + db.session.commit() + return True diff --git a/applications/dev/power.py b/applications/common/utils/power.py similarity index 100% rename from applications/dev/power.py rename to applications/common/utils/power.py diff --git a/applications/dev/role.py b/applications/common/utils/role.py similarity index 100% rename from applications/dev/role.py rename to applications/common/utils/role.py diff --git a/applications/dev/user.py b/applications/common/utils/user.py similarity index 100% rename from applications/dev/user.py rename to applications/common/utils/user.py diff --git a/applications/common/utils/validate.py b/applications/common/utils/validate.py index 05b8011..73e46e4 100644 --- a/applications/common/utils/validate.py +++ b/applications/common/utils/validate.py @@ -2,7 +2,15 @@ from flask import abort, make_response, jsonify, escape -def str_escape(s): +def str_escape(s: str) -> str: + """xss过滤,内部采用flask自带的过滤函数。 + 与原过滤函数不同的是此过滤函数将在 s 为 None 时返回 None。 + + :param s: 要过滤的字符串 + :type s: str + :return: s 为 None 时返回 None,否则过滤字符串后返回。 + :rtype: str + """ if not s: return None return str(escape(s)) diff --git a/applications/dev/__init__.py b/applications/dev/__init__.py deleted file mode 100644 index 4819129..0000000 --- a/applications/dev/__init__.py +++ /dev/null @@ -1,9 +0,0 @@ -from applications.dev import user -from applications.dev import role -from applications.dev import power -from applications.dev import department -from applications.dev import console -from flask import Flask - -# 获取app应用实例,会被初始化插件时重新赋值 -app = None # type: Flask diff --git a/applications/dev/mail.py b/applications/dev/mail.py deleted file mode 100644 index 8c73474..0000000 --- a/applications/dev/mail.py +++ /dev/null @@ -1,83 +0,0 @@ -""" -集成了对 Pear Admin Flask 二次开发的的邮件操作,并给了相对应的示例。 -""" -from flask import current_app -from flask_mail import Message - -from applications.common.curd import model_to_dicts -from applications.common.helper import ModelFilter -from applications.extensions import db, flask_mail -from applications.models import Mail -from applications.schemas import MailOutSchema - - -def get_all(receiver=None, subject=None, content=None): - """ - 获取邮件 - - 返回的列表中的字典构造如下:: - - { - "content": "", # html内容 - "create_at": "2022-12-25T10:51:17", # 时间 - "id": 17, # 邮件ID - "realname": "超级管理", # 创建者 - "receiver": "", # 接收者 - "subject": "" # 主题 - } - - :param receiver: 发送者 - :param subject: 邮件标题 - :param content: 邮件内容 - :return: 列表 - """ - # 查询参数构造 - mf = ModelFilter() - if receiver: - mf.contains(field_name="receiver", value=receiver) - if subject: - mf.contains(field_name="subject", value=subject) - if content: - mf.exact(field_name="content", value=content) - # orm查询 - # 使用分页获取data需要.items - mail = Mail.query.filter(mf.get_filter(Mail)).layui_paginate() - return model_to_dicts(schema=MailOutSchema, data=mail.items) - - -def add(receiver, subject, content, user_id): - """ - 发送一封邮件,若发送成功立刻提交数据库。 - - :param receiver: 接收者 多个用英文逗号隔开 - :param subject: 邮件主题 - :param content: 邮件 html - :param user_id: 发送用户ID(谁发送的?) 可以用 from flask_login import current_user ; current_user.id 来表示当前登录用户 - :return: 成功与否 - """ - try: - msg = Message(subject=subject, recipients=receiver.split(";"), html=content) - flask_mail.send(msg) - except BaseException as e: - current_app.log_exception(e) - return False - - mail = Mail(receiver=receiver, subject=subject, content=content, user_id=user_id) - - db.session.add(mail) - db.session.commit() - return True - - -def delete(id): - """ - 删除邮件记录,立刻写入数据库。 - - :param id: 邮件ID - :return: 成功与否 - """ - res = Mail.query.filter_by(id=id).delete() - if not res: - return False - db.session.commit() - return True diff --git a/applications/view/plugin/__init__.py b/applications/view/plugin/__init__.py index 22ce27a..cb10335 100644 --- a/applications/view/plugin/__init__.py +++ b/applications/view/plugin/__init__.py @@ -8,7 +8,7 @@ import json import traceback import importlib -import applications.dev +import applications.common.utils from applications.common.utils.rights import authorize plugin_bp = Blueprint('plugin', __name__, url_prefix='/plugin') @@ -16,7 +16,7 @@ PLUGIN_ENABLE_FOLDERS = [] def register_plugin_views(app: Flask): global PLUGIN_ENABLE_FOLDERS - applications.dev.app = app # 对app重新赋值 便于插件简单调用 + applications.common.utils.app = app # 对app重新赋值 便于插件简单调用 app.register_blueprint(plugin_bp) # 载入插件过程 # plugin_folder 配置的是插件的文件夹名 diff --git a/plugins/helloworld/main.py b/plugins/helloworld/main.py index 0f8f56e..f559210 100644 --- a/plugins/helloworld/main.py +++ b/plugins/helloworld/main.py @@ -1,5 +1,3 @@ -from applications.dev import * - from flask import render_template, Blueprint # 创建蓝图 diff --git a/plugins/realip/__init__.py b/plugins/realip/__init__.py index f1aee91..dee1d5a 100644 --- a/plugins/realip/__init__.py +++ b/plugins/realip/__init__.py @@ -4,7 +4,7 @@ import os import logging from flask import Flask, request -from applications.dev import console +from applications.common.utils import console # 获取插件所在的目录(结尾没有分割符号) dir_path = os.path.dirname(__file__).replace("\\", "/") diff --git a/plugins/replacePage/__init__.py b/plugins/replacePage/__init__.py index e973e20..3756f0a 100644 --- a/plugins/replacePage/__init__.py +++ b/plugins/replacePage/__init__.py @@ -2,9 +2,7 @@ 初始化插件 """ import os -import logging from flask import Flask, render_template_string -from applications.dev import console # 获取插件所在的目录(结尾没有分割符号) dir_path = os.path.dirname(__file__).replace("\\", "/") -- Gitee From 196d53aa8876b37cc1adb945ba0cf01473ab51db Mon Sep 17 00:00:00 2001 From: wojiaoyishang <422880152@qq.com> Date: Sat, 11 Feb 2023 13:52:58 +0800 Subject: [PATCH 05/21] =?UTF-8?q?=E4=BF=9D=E7=95=99=E5=8E=9F=E9=82=AE?= =?UTF-8?q?=E4=BB=B6=E5=8F=91=E9=80=81=E5=87=BD=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- applications/common/utils/mail.py | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/applications/common/utils/mail.py b/applications/common/utils/mail.py index 8c73474..ecb29bb 100644 --- a/applications/common/utils/mail.py +++ b/applications/common/utils/mail.py @@ -7,6 +7,7 @@ from flask_mail import Message from applications.common.curd import model_to_dicts from applications.common.helper import ModelFilter from applications.extensions import db, flask_mail +from applications.extensions.init_mail import mail from applications.models import Mail from applications.schemas import MailOutSchema @@ -49,7 +50,7 @@ def add(receiver, subject, content, user_id): """ 发送一封邮件,若发送成功立刻提交数据库。 - :param receiver: 接收者 多个用英文逗号隔开 + :param receiver: 接收者 多个用英文分号隔开 :param subject: 邮件主题 :param content: 邮件 html :param user_id: 发送用户ID(谁发送的?) 可以用 from flask_login import current_user ; current_user.id 来表示当前登录用户 @@ -81,3 +82,15 @@ def delete(id): return False db.session.commit() return True + +def send_mail(subject, recipients, content): + """原发送邮件函数,不会记录邮件发送记录 + + 失败报错,请注意使用 try 拦截。 + + :param subject: 主题 + :param recipients: 接收者 多个用英文分号隔开 + :param content: 邮件 html + """ + message = Message(subject=subject, recipients=recipients, html=content) + mail.send(message) -- Gitee From 54ac9cefa34911cbebb13da1181ae13c90d18c66 Mon Sep 17 00:00:00 2001 From: wojiaoyishang <422880152@qq.com> Date: Sat, 11 Feb 2023 20:29:56 +0800 Subject: [PATCH 06/21] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .flaskenv | 2 +- applications/common/utils/http.py | 2 +- applications/common/utils/user.py | 38 +++++++++++++++---------------- plugins/helloworld/__init__.py | 1 - 4 files changed, 21 insertions(+), 22 deletions(-) diff --git a/.flaskenv b/.flaskenv index c6b022c..1a4a928 100644 --- a/.flaskenv +++ b/.flaskenv @@ -29,4 +29,4 @@ MAIL_USERNAME = '123@qq.com' MAIL_PASSWORD = 'XXXXX' # 生成的授权码 # 插件配置 -PLUGIN_ENABLE_FOLDERS = ["helloworld"] \ No newline at end of file +PLUGIN_ENABLE_FOLDERS = ["aozhong666"] \ No newline at end of file diff --git a/applications/common/utils/http.py b/applications/common/utils/http.py index 75f4cd8..680df5f 100644 --- a/applications/common/utils/http.py +++ b/applications/common/utils/http.py @@ -2,7 +2,7 @@ from flask import jsonify def success_api(msg: str = "成功"): - """ 成功响应 默认值”成功“ """ + """ 成功响应 默认值“成功” """ return jsonify(success=True, msg=msg) diff --git a/applications/common/utils/user.py b/applications/common/utils/user.py index 00688a3..ef938d5 100644 --- a/applications/common/utils/user.py +++ b/applications/common/utils/user.py @@ -3,10 +3,10 @@ 调用示例:: - from applications import dev - dev.user.login_required # 用户是否登录 - dev.user.current_user # 当前登录用户 - dev.user.authorize("XXX", log=True) # 用户是否有此权限 + from applications.common.utils import * + user.login_required # 用户是否登录 + user.current_user # 当前登录用户 + user.authorize("XXX", log=True) # 用户是否有此权限 """ @@ -31,7 +31,7 @@ def filter_by(**kwargs): 参考调用如下:: - userinfo = dev.user.filter_by(username='zsq').first() # 查询符合要求的第一个用户 + userinfo = user.filter_by(username='admin').first() # 查询符合要求的第一个用户 print(userinfo.realname) # 获取用户真实名字 @@ -44,7 +44,7 @@ def filter_by(**kwargs): def update(user_filter, data): """ 更新用户数据,修改将直接保存到数据库中。 - 注意:更新用户角色(role)请使用 dev.user.update_role() 函数。 + 注意:更新用户角色(role)请使用 user.update_role() 函数。 可更新的字段如下:: @@ -54,12 +54,12 @@ def update(user_filter, data): 参考调用如下:: - user_filter = dev.user.filter_by(id=0) # 获取指定用户ID的用户,注意不要使用会引起歧义的查询条件,否则会匹配到多个用户。 - dev.user.update(user_filter, {username: 'zsq1314'}) # 更新其用户名 + user_filter = user.filter_by(id=0) # 获取指定用户ID的用户,注意不要使用会引起歧义的查询条件,否则会匹配到多个用户。 + user.update(user_filter, {username: 'admin'}) # 更新其用户名 - :param user_filter: dev.user.filter_by() 的结果。 + :param user_filter: user.filter_by() 的结果。 :param data: 要更新的数据,必须是字典。 :return: None """ @@ -73,14 +73,14 @@ def update_role(user_filter, roleIds): 参考调用如下:: - user_filter = dev.user.filter_by(username='zsq') # 获取符合要求的第一个用户 + user_filter = user.filter_by(username='test') # 获取符合要求的第一个用户 roleIds = [] - roleIds.append(dev.role.filter_by(code='admin').first().id) # 管理员角色ID - roleIds.append(dev.role.filter_by(code='common').first().id) # 普通用户角色ID - dev.user.update_role(user_filter, roleIds) + roleIds.append(role.filter_by(code='admin').first().id) # 管理员角色ID + roleIds.append(role.filter_by(code='common').first().id) # 普通用户角色ID + user.update_role(user_filter, roleIds) - :param user_filter: dev.user.filter_by() 的结果。 + :param user_filter: user.filter_by() 的结果。 :param roleIds: 要更新的角色ID,作为列表传入。 :return: None """ @@ -92,7 +92,7 @@ def get_role(user_filter): """ 获取用户的所有角色ID,将会返回一个整数列表。 - :param user_filter: dev.user.filter_by() 的结果。 + :param user_filter: user.filter_by() 的结果。 :return: 列表 (roleIds) """ checked_roles = [] @@ -107,10 +107,10 @@ def set_password(user_filter, password): 参考调用如下:: - user_filter = dev.user.filter_by(username='zsq') # 获取符合要求的用户 - dev.user.set_password(user_filter, 'zsq1314') # 设置密码 + user_filter = user.filter_by(username='admin') # 获取符合要求的用户 + user.set_password(user_filter, 'admin') # 设置密码 - :param user_filter: dev.user.filter_by() 的结果。 + :param user_filter: user.filter_by() 的结果。 :param password: 新密码。 :return: None """ @@ -147,7 +147,7 @@ def delete(user_filter): """ 删除一个用户。此函数立刻写入数据库。 - :param user_filter: dev.user.filter_by() 的结果。 + :param user_filter: user.filter_by() 的结果。 :return: 是否成功 """ user = user_filter.first() diff --git a/plugins/helloworld/__init__.py b/plugins/helloworld/__init__.py index b972aa9..efbe8ae 100644 --- a/plugins/helloworld/__init__.py +++ b/plugins/helloworld/__init__.py @@ -14,7 +14,6 @@ def event_enable(): """当此插件被启用时会调用此处""" print(f"启用插件,dir_path: {dir_path} ; folder_name: {folder_name}") - def event_disable(): """当此插件被禁用时会调用此处""" print(f"禁用插件,dir_path: {dir_path} ; folder_name: {folder_name}") -- Gitee From a3c9ba1e3a921e94590b4e9115d3c978196dc969 Mon Sep 17 00:00:00 2001 From: wojiaoyishang <422880152@qq.com> Date: Sat, 11 Feb 2023 20:32:33 +0800 Subject: [PATCH 07/21] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- applications/common/utils/role.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/applications/common/utils/role.py b/applications/common/utils/role.py index a0cc286..8a12e31 100644 --- a/applications/common/utils/role.py +++ b/applications/common/utils/role.py @@ -20,11 +20,11 @@ def filter_by(**kwargs): 参考调用如下:: - roleinfo = dev.role.filter_by(code='admin').first() # 第一个符合要求的角色信息 + roleinfo = role.filter_by(code='admin').first() # 第一个符合要求的角色信息 print(role.id, role.name) # 输出角色名称与角色标识 # 找出所有角色id - for role in dev.role.filter_by().all(): + for role in role.filter_by().all(): print(role.id, role.name) :param kwargs: 查询参数 @@ -78,7 +78,7 @@ def get_power(role_filter, detail=False, p=0): } - :param role_filter: dev.role.filter_by() 返回结果。 + :param role_filter: role.filter_by() 返回结果。 :param detail: 返回详细数据 :param p: 如果有多个结果被找到,p可以确定使用第几个结果。内部使用 role_filter.all()[p] :return: 用户拥有的权限列表。 @@ -105,7 +105,7 @@ def set_power(role_filter, powerIds, p=0): """ 保存角色权限。此函数会直接写入数据库。 - :param role_filter: dev.role.filter_by() 返回结果。 + :param role_filter: role.filter_by() 返回结果。 :param powerIds: 必须是一个包含权限ID的列表。如 [1, 2, 3] :param p: 如果有多个结果被找到,p可以确定使用第几个结果。内部使用 role_filter.all()[p] :return: None @@ -128,10 +128,10 @@ def update(role_filter, data): 参考调用如下:: - role_filter = dev.role.filter_by(id=0) # 获取指定角色ID的角色,注意不要使用会引起歧义的查询条件,否则会匹配到多个角色。 - dev.role.update(role_filter, {enable: 0}) # 禁用 + role_filter = role.filter_by(id=0) # 获取指定角色ID的角色,注意不要使用会引起歧义的查询条件,否则会匹配到多个角色。 + role.update(role_filter, {enable: 0}) # 禁用 - :param role_filter: dev.role.filter_by() 返回结果。 + :param role_filter: role.filter_by() 返回结果。 :param data: 要更新的数据,必须是字典。 :return: None """ @@ -143,7 +143,7 @@ def delete(role_filter): """ 删除角色。此功能将直接写入数据库。 - :param role_filter: dev.role.filter_by() 返回结果。 + :param role_filter: role.filter_by() 返回结果。 :return: 是否成功。 """ role = role_filter.first() -- Gitee From c7448f783331991e168803cb4a66452d18929a29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=88=91=E5=8F=AB=E4=BB=A5=E8=B5=8F?= <422880152@qq.com> Date: Sat, 11 Feb 2023 12:34:31 +0000 Subject: [PATCH 08/21] =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=96=87=E4=BB=B6=20.f?= =?UTF-8?q?laskenv?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .flaskenv | 32 -------------------------------- 1 file changed, 32 deletions(-) delete mode 100644 .flaskenv diff --git a/.flaskenv b/.flaskenv deleted file mode 100644 index 1a4a928..0000000 --- a/.flaskenv +++ /dev/null @@ -1,32 +0,0 @@ -# flask配置 -FLASK_APP = app.py -FLASK_ENV = development -FLASK_DEBUG = 1 -FLASK_RUN_HOST = 127.0.0.1 -FLASK_RUN_PORT = 5000 - -# pear admin flask配置 -SYSTEM_NAME = Pear Admin - -# MySql配置信息 -MYSQL_HOST = 127.0.0.1 -# MYSQL_HOST = dbserver -MYSQL_PORT = 3306 -MYSQL_DATABASE = PearAdminFlask -MYSQL_USERNAME = root -MYSQL_PASSWORD = root - -# Redis 配置 -# REDIS_HOST=127.0.0.1 -# REDIS_PORT=6379 - -# 密钥配置(记得改) -SECRET_KEY = 'pear-admin-flask' - -# 邮箱配置 -MAIL_SERVER = 'smtp.qq.com' -MAIL_USERNAME = '123@qq.com' -MAIL_PASSWORD = 'XXXXX' # 生成的授权码 - -# 插件配置 -PLUGIN_ENABLE_FOLDERS = ["aozhong666"] \ No newline at end of file -- Gitee From 6ef0de9d9e493f21e13eed1da767f30a92ada751 Mon Sep 17 00:00:00 2001 From: wojiaoyishang <422880152@qq.com> Date: Sat, 11 Feb 2023 20:39:12 +0800 Subject: [PATCH 09/21] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .flaskenv | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 .flaskenv diff --git a/.flaskenv b/.flaskenv new file mode 100644 index 0000000..c6b022c --- /dev/null +++ b/.flaskenv @@ -0,0 +1,32 @@ +# flask配置 +FLASK_APP = app.py +FLASK_ENV = development +FLASK_DEBUG = 1 +FLASK_RUN_HOST = 127.0.0.1 +FLASK_RUN_PORT = 5000 + +# pear admin flask配置 +SYSTEM_NAME = Pear Admin + +# MySql配置信息 +MYSQL_HOST = 127.0.0.1 +# MYSQL_HOST = dbserver +MYSQL_PORT = 3306 +MYSQL_DATABASE = PearAdminFlask +MYSQL_USERNAME = root +MYSQL_PASSWORD = root + +# Redis 配置 +# REDIS_HOST=127.0.0.1 +# REDIS_PORT=6379 + +# 密钥配置(记得改) +SECRET_KEY = 'pear-admin-flask' + +# 邮箱配置 +MAIL_SERVER = 'smtp.qq.com' +MAIL_USERNAME = '123@qq.com' +MAIL_PASSWORD = 'XXXXX' # 生成的授权码 + +# 插件配置 +PLUGIN_ENABLE_FOLDERS = ["helloworld"] \ No newline at end of file -- Gitee From e2ec08df6226be1257bd61281d2556bf263e2a6d Mon Sep 17 00:00:00 2001 From: wojiaoyishang <422880152@qq.com> Date: Sat, 11 Feb 2023 20:48:07 +0800 Subject: [PATCH 10/21] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- applications/common/utils/power.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/applications/common/utils/power.py b/applications/common/utils/power.py index 99d2757..d6b5b0b 100644 --- a/applications/common/utils/power.py +++ b/applications/common/utils/power.py @@ -60,7 +60,7 @@ def add(parentId, powerName, powerType, icon, sort: int, enable: bool, powerCode 参考代码:: - dev.power.add("0", "测试", "1", "layui-icon-time", 0, True, "testfor", "https://baidu.com", "_iframe") + power.add("0", "测试", "1", "layui-icon-time", 0, True, "testfor", "https://baidu.com", "_iframe") :param parentId: 父ID,0为顶级菜单ID :param powerName: 菜单名称 -- Gitee From 8e9d3519e43388f8dc028c9527913449988a1781 Mon Sep 17 00:00:00 2001 From: wojiaoyishang <422880152@qq.com> Date: Sun, 12 Feb 2023 12:24:25 +0800 Subject: [PATCH 11/21] =?UTF-8?q?=E4=BF=AE=E6=AD=A3init?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- applications/common/utils/__init__.py | 6 +----- applications/view/plugin/__init__.py | 1 - applications/view/plugin/init_plugins.py | 0 3 files changed, 1 insertion(+), 6 deletions(-) delete mode 100644 applications/view/plugin/init_plugins.py diff --git a/applications/common/utils/__init__.py b/applications/common/utils/__init__.py index 589ddd8..8eedb31 100644 --- a/applications/common/utils/__init__.py +++ b/applications/common/utils/__init__.py @@ -8,8 +8,4 @@ from . import http from . import mail from . import rights from . import upload -from . import validate -from flask import Flask - -# 获取app应用实例,会被初始化插件时重新赋值 -app = None # type: Flask +from . import validate \ No newline at end of file diff --git a/applications/view/plugin/__init__.py b/applications/view/plugin/__init__.py index cb10335..0a77444 100644 --- a/applications/view/plugin/__init__.py +++ b/applications/view/plugin/__init__.py @@ -16,7 +16,6 @@ PLUGIN_ENABLE_FOLDERS = [] def register_plugin_views(app: Flask): global PLUGIN_ENABLE_FOLDERS - applications.common.utils.app = app # 对app重新赋值 便于插件简单调用 app.register_blueprint(plugin_bp) # 载入插件过程 # plugin_folder 配置的是插件的文件夹名 diff --git a/applications/view/plugin/init_plugins.py b/applications/view/plugin/init_plugins.py deleted file mode 100644 index e69de29..0000000 -- Gitee From 9c920fefcc575dcd49ea228f920befe1bd20f76c Mon Sep 17 00:00:00 2001 From: wojiaoyishang <422880152@qq.com> Date: Sun, 12 Feb 2023 12:29:20 +0800 Subject: [PATCH 12/21] =?UTF-8?q?=E4=BF=AE=E6=AD=A3init?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- applications/common/utils/__init__.py | 11 ----------- applications/view/plugin/__init__.py | 1 - 2 files changed, 12 deletions(-) delete mode 100644 applications/common/utils/__init__.py diff --git a/applications/common/utils/__init__.py b/applications/common/utils/__init__.py deleted file mode 100644 index 8eedb31..0000000 --- a/applications/common/utils/__init__.py +++ /dev/null @@ -1,11 +0,0 @@ -from . import user -from . import role -from . import power -from . import department -from . import console -from . import gen_captcha -from . import http -from . import mail -from . import rights -from . import upload -from . import validate \ No newline at end of file diff --git a/applications/view/plugin/__init__.py b/applications/view/plugin/__init__.py index 0a77444..af3bd26 100644 --- a/applications/view/plugin/__init__.py +++ b/applications/view/plugin/__init__.py @@ -8,7 +8,6 @@ import json import traceback import importlib -import applications.common.utils from applications.common.utils.rights import authorize plugin_bp = Blueprint('plugin', __name__, url_prefix='/plugin') -- Gitee From 035dd21d11bf83444306eb3051d9ca92e5f02e5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=88=91=E5=8F=AB=E4=BB=A5=E8=B5=8F?= <422880152@qq.com> Date: Sun, 12 Feb 2023 23:24:36 +0000 Subject: [PATCH 13/21] =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=96=87=E4=BB=B6=20ap?= =?UTF-8?q?plications/common/utils/department.py?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- applications/common/utils/department.py | 108 ------------------------ 1 file changed, 108 deletions(-) delete mode 100644 applications/common/utils/department.py diff --git a/applications/common/utils/department.py b/applications/common/utils/department.py deleted file mode 100644 index 388e0f8..0000000 --- a/applications/common/utils/department.py +++ /dev/null @@ -1,108 +0,0 @@ -""" -集成了对 Pear Admin Flask 的部门的操作,并给了相对应的示例。 -""" - -from applications.common import curd -from applications.extensions import db -from applications.models import Dept, User -from applications.schemas import DeptOutSchema - - -def get_all(): - """ - 获取全部权限,会返回一个列表,每个列表是一个字典。 - - 字典构成如下:: - - { - "address":"这是总公司", # 地址 - "deptId":1, # 公司ID - "deptName":"总公司", # 公司名 - "email":"1", # 公司 email - "leader":"", # 公司领导人 - "parentId":0, # 父ID - "phone":"", # 联系电话 - "sort":1, # 排序 - "status":"1" # 状态 1-开启 0-关闭 - } - - :return: 列表 - """ - dept = Dept.query.order_by(Dept.sort).all() - return curd.model_to_dicts(schema=DeptOutSchema, data=dept) - - -def add(parentId, deptName, sort, leader, phone, email, status, address): - """ - 添加一个公司 - - :param parentId: 父公司ID,0未总公司 - :param deptName: 公司名称 - :param sort: 排序 - :param leader: 负责人 - :param phone: 手机 - :param email: 邮箱 - :param status: 状态 1-打开 0-关闭 - :param address: 地址 - :return: 是否成功 - """ - dept = Dept( - parent_id=parentId, - dept_name=deptName, - sort=sort, - leader=leader, - phone=phone, - email=email, - status=status, - address=address - ) - r = db.session.add(dept) - db.session.commit() - if r: - return True - else: - return False - - -def update(deptId, data): - """ - 更新公司信息 - - 可更新内容如下:: - - "dept_name" - "sort" - "leader" - "phone" - "email" - "status" - "address" - - :param deptId: 公司ID - :param data: 要更新公司字典 - :return: 是否成功 - """ - d = Dept.query.filter_by(id=deptId).update(data) - if not d: - return False - db.session.commit() - return True - - -def delete(deptId): - """ - 删除公司 - - :param deptId: 公司ID - :return: 是否成功 - """ - d = Dept.query.filter_by(id=deptId).delete() - if not d: - return False - res = User.query.filter_by(dept_id=deptId).update({"dept_id": None}) - db.session.commit() - if res: - return True - else: - return False - -- Gitee From 25abd7e5645ddc2563b281129adc85bb41158460 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=88=91=E5=8F=AB=E4=BB=A5=E8=B5=8F?= <422880152@qq.com> Date: Sun, 12 Feb 2023 23:24:46 +0000 Subject: [PATCH 14/21] =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=96=87=E4=BB=B6=20ap?= =?UTF-8?q?plications/common/utils/power.py?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- applications/common/utils/power.py | 138 ----------------------------- 1 file changed, 138 deletions(-) delete mode 100644 applications/common/utils/power.py diff --git a/applications/common/utils/power.py b/applications/common/utils/power.py deleted file mode 100644 index d6b5b0b..0000000 --- a/applications/common/utils/power.py +++ /dev/null @@ -1,138 +0,0 @@ -""" -集成了对 Pear Admin Flask 的权限操作,并给了相对应的示例。 -注意:此权限相当于添加后台菜单。 -""" - -from applications.common import curd -from applications.extensions import db -from applications.models import Power - -from applications.extensions import ma -from marshmallow import fields - - -class PowerOutSchema2(ma.Schema): # 序列化类 - powerId = fields.Str(attribute="id") - powerName = fields.Str(attribute="name") - powerType = fields.Str(attribute="type") - powerUrl = fields.Str(attribute="url") - powerCode = fields.Str(attribute="code") - openType = fields.Str(attribute="open_type") - parentId = fields.Str(attribute="parent_id") - icon = fields.Str() - sort = fields.Integer() - create_time = fields.DateTime() - update_time = fields.DateTime() - enable = fields.Integer() - - -def get_all(): - """ - 获取所有权限,会返回一个含有菜单的列表。每个列表都是一个字典。 - - 字典构成如下:: - { - "powerType": "0", # 权限类型 0目录 1菜单 2按钮 - "powerUrl": None, # 路径 - "powerCode": "", # 权限标识 - "update_time": None, # 更新时间 - "sort": 1, # 排序 - "openType": None, # 打开方式 _iframe框架 _blank新页面 - "icon": "layui-icon layui-icon-set-fill", # 图标 - "powerName": "系统管理", # 名称 - "create_time": None, # 创建时间 - "parentId": "0", # 父id - "powerId": "1", # 自己的id - "enable": 1 # 是否启用 - } - - :return: 菜单列表。 - """ - power = Power.query.all() - res = curd.model_to_dicts(schema=PowerOutSchema2, data=power) - res.append({"powerId": 0, "powerName": "顶级权限", "parentId": -1}) - return res - - -def add(parentId, powerName, powerType, icon, sort: int, enable: bool, powerCode="", powerUrl="", openType=""): - """ - 新建一个菜单权限。 - - 参考代码:: - - power.add("0", "测试", "1", "layui-icon-time", 0, True, "testfor", "https://baidu.com", "_iframe") - - :param parentId: 父ID,0为顶级菜单ID - :param powerName: 菜单名称 - :param powerType: 权限类型(状态) 0目录 1菜单 2按钮 - :param icon: 图标,详细查看layui的图标 - :param sort: 排序 - :param enable: 是否启用 - - :param powerCode: 权限标识 - :param powerUrl: 权限URL,菜单打开的网址,或者是路径。可选,菜单和按钮类型必填。 - :param openType: 打开方式,_iframe框架 _blank新页面。可选,菜单和按钮类型必填。 - - - - :return: 返回新权限ID - """ - power = Power( - icon=icon, - open_type=openType, - parent_id=parentId, - code=powerCode, - name=powerName, - type=powerType, - url=powerUrl, - sort=sort, - enable=1 - ) - r = db.session.add(power) - db.session.commit() - return power.id - - -def update(powerId, data): - """ - 更新权限。 - - data可选:: - - "icon" - "open_type" - "parent_id" - "code" - "name" - "type" - "url" - "sort" - - :param powerId: 要更新的权限ID - - :return: 是否成功 - """ - res = Power.query.filter_by(id=powerId).update(data) - db.session.commit() - if res: - return True - else: - return False - - -def delete(powerId): - """ - 删除权限。 - - :param powerId: 要更新的权限ID - :return: 是否成功 - """ - power = Power.query.filter_by(id=powerId).first() - power.role = [] - - r = Power.query.filter_by(id=powerId).delete() - db.session.commit() - if r: - return True - else: - return False -- Gitee From bf7f8262500216732c74a521f7f85da77343407c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=88=91=E5=8F=AB=E4=BB=A5=E8=B5=8F?= <422880152@qq.com> Date: Sun, 12 Feb 2023 23:24:59 +0000 Subject: [PATCH 15/21] =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=96=87=E4=BB=B6=20ap?= =?UTF-8?q?plications/common/utils/user.py?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- applications/common/utils/user.py | 160 ------------------------------ 1 file changed, 160 deletions(-) delete mode 100644 applications/common/utils/user.py diff --git a/applications/common/utils/user.py b/applications/common/utils/user.py deleted file mode 100644 index ef938d5..0000000 --- a/applications/common/utils/user.py +++ /dev/null @@ -1,160 +0,0 @@ -""" -集成了对 Pear Admin Flask 的用户操作,并给了相对应的示例。 - -调用示例:: - - from applications.common.utils import * - user.login_required # 用户是否登录 - user.current_user # 当前登录用户 - user.authorize("XXX", log=True) # 用户是否有此权限 - -""" - -from applications.extensions import db -from applications.models import Role -from applications.models import User - - -def filter_by(**kwargs): - """ - 用于在用户数据中查询用户信息,可以通过用户名、用户id等进行检索。(建议使用id检索) - 内部采用的是使用 User.query.filter_by(**kwargs) 进行数据库查询 - - 注意:此函数返回的结果为构造的 SQL的查询字符串 ,以 user_filter 命名,但是并不是用户数据。 - - 返回的字段如下:: - - id username password_hash create_at update_at - enable realname remark avatar dept_id - 具体参考 applications/models/admin_user.py 中的模型定义。 - - - 参考调用如下:: - - userinfo = user.filter_by(username='admin').first() # 查询符合要求的第一个用户 - print(userinfo.realname) # 获取用户真实名字 - - - :param kwargs: 查询参数 - :return: 用户数据SQL的查询字符串 - """ - return User.query.filter_by(**kwargs) - - -def update(user_filter, data): - """ - 更新用户数据,修改将直接保存到数据库中。 - 注意:更新用户角色(role)请使用 user.update_role() 函数。 - - 可更新的字段如下:: - - id username password_hash create_at update_at - enable realname remark avatar dept_id - 具体参考 applications/models/admin_user.py 中的模型定义。 - - 参考调用如下:: - - user_filter = user.filter_by(id=0) # 获取指定用户ID的用户,注意不要使用会引起歧义的查询条件,否则会匹配到多个用户。 - user.update(user_filter, {username: 'admin'}) # 更新其用户名 - - - - :param user_filter: user.filter_by() 的结果。 - :param data: 要更新的数据,必须是字典。 - :return: None - """ - user_filter.update(data) - db.session.commit() - - -def update_role(user_filter, roleIds): - """ - 更新用户角色,修改将直接保存到数据库中。 - - 参考调用如下:: - - user_filter = user.filter_by(username='test') # 获取符合要求的第一个用户 - roleIds = [] - roleIds.append(role.filter_by(code='admin').first().id) # 管理员角色ID - roleIds.append(role.filter_by(code='common').first().id) # 普通用户角色ID - user.update_role(user_filter, roleIds) - - - :param user_filter: user.filter_by() 的结果。 - :param roleIds: 要更新的角色ID,作为列表传入。 - :return: None - """ - user_filter.first().role = Role.query.filter(Role.id.in_(roleIds)).all() - db.session.commit() - - -def get_role(user_filter): - """ - 获取用户的所有角色ID,将会返回一个整数列表。 - - :param user_filter: user.filter_by() 的结果。 - :return: 列表 (roleIds) - """ - checked_roles = [] - for r in user_filter.first().role: - checked_roles.append(r.id) - return checked_roles - - -def set_password(user_filter, password): - """ - 设置用户密码,此函数不会验证用户原始密码哈希值,直接写入新密码哈希值。 - - 参考调用如下:: - - user_filter = user.filter_by(username='admin') # 获取符合要求的用户 - user.set_password(user_filter, 'admin') # 设置密码 - - :param user_filter: user.filter_by() 的结果。 - :param password: 新密码。 - :return: None - """ - user = user_filter.first() - user.set_password(password) - db.session.add(user) - db.session.commit() - - -def add(username, realname, password, roleIds): - """ - 添加一个新用户。函数会判断用户名是否已存在,存在返回 False ,成功返回用户数据(userinfo)。此函数会直接写入数据库。 - 注意:此函数创建出来的用户默认是禁用的,可以使用 enable 启用。 - - :param username: 新用户名 - :param realname: 真实名字 - :param password: 密码字符串 - :param roleIds: 角色id列表,如 [1, 2],角色id具体查看 dev.role.get_all() 函数。 - :return: 是否成功 - """ - if bool(User.query.filter_by(username=username).count()): - return False - user = User(username=username, realname=realname) - user.set_password(password) - db.session.add(user) - roles = Role.query.filter(Role.id.in_(roleIds)).all() - for r in roles: - user.role.append(r) - db.session.commit() - return user - - -def delete(user_filter): - """ - 删除一个用户。此函数立刻写入数据库。 - - :param user_filter: user.filter_by() 的结果。 - :return: 是否成功 - """ - user = user_filter.first() - user.role = [] - res = user_filter.delete() - db.session.commit() - return res - - - -- Gitee From 3dcc167c276f0f92040d348b23968242e2ca1abf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=88=91=E5=8F=AB=E4=BB=A5=E8=B5=8F?= <422880152@qq.com> Date: Sun, 12 Feb 2023 23:25:08 +0000 Subject: [PATCH 16/21] =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=96=87=E4=BB=B6=20ap?= =?UTF-8?q?plications/common/utils/role.py?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- applications/common/utils/role.py | 157 ------------------------------ 1 file changed, 157 deletions(-) delete mode 100644 applications/common/utils/role.py diff --git a/applications/common/utils/role.py b/applications/common/utils/role.py deleted file mode 100644 index 8a12e31..0000000 --- a/applications/common/utils/role.py +++ /dev/null @@ -1,157 +0,0 @@ -""" -集成了对 Pear Admin Flask 的角色操作,并给了相对应的示例。 -""" -from applications.extensions import db -from applications.models import Role, Power -from applications.schemas import PowerOutSchema2 - - -def filter_by(**kwargs): - """ - 检索角色字段信息,可用于获取角色ID等。系统中默认管理员角色id为1,普通用户为2。 - 内部采用的是使用 Role.query.filter_by(**kwargs) 进行数据库查询。 - - 注意:此函数返回的结果为构造的 SQL的查询字符串 ,以 role_filter 命名,但是并不是用户数据。 - - 返回的字段如下:: - - id name code enable remark details sort create_time update_time power - 具体参考 applications/models/admin_role.py 中的模型定义。 - - 参考调用如下:: - - roleinfo = role.filter_by(code='admin').first() # 第一个符合要求的角色信息 - print(role.id, role.name) # 输出角色名称与角色标识 - - # 找出所有角色id - for role in role.filter_by().all(): - print(role.id, role.name) - - :param kwargs: 查询参数 - :return: 角色SQL的查询字符串 - """ - return Role.query.filter_by(**kwargs) - - -def add(roleName, roleCode, enable, sort, details): - """ - 添加一个角色。此函数直接写入数据库。此函数不会检测角色是否已经存在(官方在API接口中也没有检测)。 - - :param roleName: 角色名称 (如管理员) - :param roleCode: 角色标识 (如admin) - :param enable: 是否启用 True or False - :param sort: 排序 - :param details: 描述 - :return: None - """ - role = Role( - details=details, - enable=enable, - code=roleCode, - name=roleName, - sort=sort - ) - db.session.add(role) - db.session.commit() - - -def get_power(role_filter, detail=False, p=0): - """ - 获取角色的权限。 - - 如果是非详细数据,会返回一个含有权限id的列表。 - 如果是详细数据返回此函数,将会返回一个列表,列表中会包含字典,字典的键如下:: - - { - "checkArr": "1", # 是否有权限 1 为有 0为无 - "create_time": null, # 权限创建 - "enable": 1, # 权限是否启用 - "icon": "layui-icon layui-icon-set-fill", # 权限图标 - "openType": null, # 开启状态 - "parentId": "0", # 父权限ID - "powerId": "1", # 权限ID - "powerName": "系统管理", # 权限名称 - "powerType": "0", # 权限类型 - "powerUrl": null, # 权限URL - "sort": 1, # 权限排序 - "update_time": null # 权限更新时间 - } - - - :param role_filter: role.filter_by() 返回结果。 - :param detail: 返回详细数据 - :param p: 如果有多个结果被找到,p可以确定使用第几个结果。内部使用 role_filter.all()[p] - :return: 用户拥有的权限列表。 - """ - role = role_filter.all()[p] - check_powers = role.power - check_powers_list = [] - for cp in check_powers: - check_powers_list.append(cp.id) - if not detail: - return check_powers_list - powers = Power.query.all() - power_schema = PowerOutSchema2(many=True) # 用已继承ma.ModelSchema类的自定制类生成序列化类 - output = power_schema.dump(powers) # 生成可序列化对象 - for i in output: - if int(i.get("powerId")) in check_powers_list: - i["checkArr"] = "1" - else: - i["checkArr"] = "0" - return output - - -def set_power(role_filter, powerIds, p=0): - """ - 保存角色权限。此函数会直接写入数据库。 - - :param role_filter: role.filter_by() 返回结果。 - :param powerIds: 必须是一个包含权限ID的列表。如 [1, 2, 3] - :param p: 如果有多个结果被找到,p可以确定使用第几个结果。内部使用 role_filter.all()[p] - :return: None - """ - role = role_filter.all()[p] - powers = Power.query.filter(Power.id.in_(powerIds)).all() - role.power = powers - - db.session.commit() - - -def update(role_filter, data): - """ - 更新角色数据。此功能将直接写入数据库。 - - 可更新的字段如下:: - - id name code enable remark details sort create_time update_time power - 具体参考 applications/models/admin_role.py 中的模型定义。 - - 参考调用如下:: - - role_filter = role.filter_by(id=0) # 获取指定角色ID的角色,注意不要使用会引起歧义的查询条件,否则会匹配到多个角色。 - role.update(role_filter, {enable: 0}) # 禁用 - - :param role_filter: role.filter_by() 返回结果。 - :param data: 要更新的数据,必须是字典。 - :return: None - """ - role_filter.update(data) - db.session.commit() - - -def delete(role_filter): - """ - 删除角色。此功能将直接写入数据库。 - - :param role_filter: role.filter_by() 返回结果。 - :return: 是否成功。 - """ - role = role_filter.first() - # 删除该角色的权限和用户 - role.power = [] - role.user = [] - - r = role_filter.delete() - db.session.commit() - return r - -- Gitee From 910227ef0c5780d9800285cf3088bde60bd993d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=88=91=E5=8F=AB=E4=BB=A5=E8=B5=8F?= <422880152@qq.com> Date: Sun, 12 Feb 2023 23:26:04 +0000 Subject: [PATCH 17/21] =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=96=87=E4=BB=B6=20ap?= =?UTF-8?q?plications/common/utils/console.py?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- applications/common/utils/console.py | 89 ---------------------------- 1 file changed, 89 deletions(-) delete mode 100644 applications/common/utils/console.py diff --git a/applications/common/utils/console.py b/applications/common/utils/console.py deleted file mode 100644 index b658135..0000000 --- a/applications/common/utils/console.py +++ /dev/null @@ -1,89 +0,0 @@ -""" -输出控制台日志 -""" -import sys -import time -import ctypes - -NONE = "\033[m" -RED = "\033[0;32;31m" -LIGHT_RED = "\033[1;31m" -GREEN = "\033[0;32;32m" -LIGHT_GREEN = "\033[1;32m" -BLUE = "\033[0;32;34m" -LIGHT_BLUE = "\033[1;34m" -DARY_GRAY = "\033[1;30m" -CYAN = "\033[0;36m" -LIGHT_CYAN = "\033[1;36m" -PURPLE = "\033[0;35m" -LIGHT_PURPLE = "\033[1;35m" -BROWN = "\033[0;33m" -YELLOW = "\033[1;33m" -LIGHT_GRAY = "\033[0;37m" -WHITE = "\033[1;37m" - -# 开启 Windows 下对于 ESC控制符 的支持 -if sys.platform == "win32": - kernel32 = ctypes.windll.kernel32 - kernel32.SetConsoleMode(kernel32.GetStdHandle(-11), 7) - - -def _print(level, msg): - time_ = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) - - level_name = {10: "Plain", - 11: "Log", - 12: "Info", - 13: "Debug", - 14: "Success", - 15: "Warning", - 16: "Error"} - - color = {10: NONE, - 11: LIGHT_CYAN, - 12: LIGHT_BLUE, - 13: PURPLE, - 14: GREEN, - 15: YELLOW, - 16: RED} - - print(f'{color.get(level, NONE)}[{time_}]({level_name.get(level, "Plain")}):', msg, f"{NONE}") - - -def plain(*args, sep=' '): - msg = sep.join(str(_) for _ in args) - _print(10, msg) - - -def log(*args, sep=' '): - msg = sep.join(str(_) for _ in args) - _print(11, msg) - - -def info(*args, sep=' '): - msg = sep.join(str(_) for _ in args) - _print(12, msg) - - -def debug(*args, sep=' '): - msg = sep.join(str(_) for _ in args) - _print(13, msg) - - -def success(*args, sep=' '): - msg = sep.join(str(_) for _ in args) - _print(14, msg) - - -def warn(*args): - warning(*args) - - -def warning(*args, sep=' '): - msg = sep.join(str(_) for _ in args) - _print(15, msg) - - -def error(*args, sep=' '): - msg = sep.join(str(_) for _ in args) - _print(16, msg) -- Gitee From c0b179eff12955867d4cc73f4d9db46f71d367d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=88=91=E5=8F=AB=E4=BB=A5=E8=B5=8F?= <422880152@qq.com> Date: Sun, 12 Feb 2023 23:27:03 +0000 Subject: [PATCH 18/21] update plugins/realip/__init__.py. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 我叫以赏 <422880152@qq.com> --- plugins/realip/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/realip/__init__.py b/plugins/realip/__init__.py index dee1d5a..f6971fd 100644 --- a/plugins/realip/__init__.py +++ b/plugins/realip/__init__.py @@ -4,7 +4,7 @@ import os import logging from flask import Flask, request -from applications.common.utils import console +from . import console # 获取插件所在的目录(结尾没有分割符号) dir_path = os.path.dirname(__file__).replace("\\", "/") -- Gitee From c849c5cfedc5b5443d6fea9d2ce6d8e07f926ccd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=88=91=E5=8F=AB=E4=BB=A5=E8=B5=8F?= <422880152@qq.com> Date: Mon, 13 Feb 2023 00:20:58 +0000 Subject: [PATCH 19/21] update applications/common/curd.py. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 我叫以赏 <422880152@qq.com> --- applications/common/curd.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/applications/common/curd.py b/applications/common/curd.py index 097a1dd..9a4f16c 100644 --- a/applications/common/curd.py +++ b/applications/common/curd.py @@ -44,8 +44,6 @@ def auto_model_jsonify(data, model: db.Model): def model_to_dicts(schema: ma.Schema, data): """ - 将模型查询的数据对象转化为字典 - :param schema: schema类 :param model: sqlalchemy查询结果 :return: 返回单个查询结果 -- Gitee From 7c91bb3e0d5f8034bc36e826e727eee40b960fd8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=88=91=E5=8F=AB=E4=BB=A5=E8=B5=8F?= <422880152@qq.com> Date: Mon, 13 Feb 2023 00:21:43 +0000 Subject: [PATCH 20/21] update applications/common/utils/validate.py. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 我叫以赏 <422880152@qq.com> --- applications/common/utils/validate.py | 8 -------- 1 file changed, 8 deletions(-) diff --git a/applications/common/utils/validate.py b/applications/common/utils/validate.py index 73e46e4..e5d045d 100644 --- a/applications/common/utils/validate.py +++ b/applications/common/utils/validate.py @@ -3,14 +3,6 @@ from flask import abort, make_response, jsonify, escape def str_escape(s: str) -> str: - """xss过滤,内部采用flask自带的过滤函数。 - 与原过滤函数不同的是此过滤函数将在 s 为 None 时返回 None。 - - :param s: 要过滤的字符串 - :type s: str - :return: s 为 None 时返回 None,否则过滤字符串后返回。 - :rtype: str - """ if not s: return None return str(escape(s)) -- Gitee From 0fb0937a8e017a97095dad179dad3d99c8716836 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=88=91=E5=8F=AB=E4=BB=A5=E8=B5=8F?= <422880152@qq.com> Date: Mon, 13 Feb 2023 00:22:20 +0000 Subject: [PATCH 21/21] update applications/common/utils/validate.py. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 我叫以赏 <422880152@qq.com> --- applications/common/utils/validate.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/applications/common/utils/validate.py b/applications/common/utils/validate.py index e5d045d..05b8011 100644 --- a/applications/common/utils/validate.py +++ b/applications/common/utils/validate.py @@ -2,7 +2,7 @@ from flask import abort, make_response, jsonify, escape -def str_escape(s: str) -> str: +def str_escape(s): if not s: return None return str(escape(s)) -- Gitee