diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000000000000000000000000000000000000..467e583ef4368663d297ef46d9db6389378783ba --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,24 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "Python: Flask", + "type": "python", + "request": "launch", + "module": "flask", + "env": { + "FLASK_APP": "app.py", + "FLASK_DEBUG": "1" + }, + "args": [ + "run", + "-p 8000" + ], + "jinja": true, + "justMyCode": true + } + ] +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000000000000000000000000000000000000..d99f2f30ccdcfdaa059508e5f2a71c8d80d9f88d --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,6 @@ +{ + "[python]": { + "editor.defaultFormatter": "ms-python.black-formatter" + }, + "python.formatting.provider": "none" +} \ No newline at end of file diff --git a/applications/__init__.py b/applications/__init__.py index 21f1d306c8f9dab798d01363bf57300762d4f0a5..ad412bf0f4885cdf1443a4b38b8930a5339b0375 100644 --- a/applications/__init__.py +++ b/applications/__init__.py @@ -5,7 +5,6 @@ from applications.config import BaseConfig from applications.extensions import init_plugs from applications.view import init_view - def create_app(): app = Flask(os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))) # 引入数据库配置 diff --git a/applications/common/script/admin.py b/applications/common/script/admin.py index 2cf39419381c617196736870d99c82c7f34c9165..eb09484b3d9bdf319ffe9bd7cb7796a905286e5a 100644 --- a/applications/common/script/admin.py +++ b/applications/common/script/admin.py @@ -3,7 +3,7 @@ import datetime from flask.cli import AppGroup from applications.extensions import db -from applications.models import User, Role, Dept, Power +from applications.models import User, Role, Power admin_cli = AppGroup("admin") @@ -63,72 +63,72 @@ roledata = [ create_time=now_time, ) ] -deptdata = [ - Dept( - id=1, - parent_id=0, - dept_name='总公司', - sort=1, - leader='就眠仪式', - phone='12312345679', - email='123qq.com', - status=1, - remark='这是总公司', - create_at=now_time - ), - Dept( - id=4, - parent_id=1, - dept_name='济南分公司', - sort=2, - leader='就眠仪式', - phone='12312345679', - email='123qq.com', - status=1, - remark='这是济南', - create_at=now_time - - ), - Dept( - id=5, - parent_id=1, - dept_name='唐山分公司', - sort=4, - leader='mkg', - phone='12312345679', - email='123qq.com', - status=1, - remark='这是唐山', - create_at=now_time - - ), - Dept( - id=7, - parent_id=4, - dept_name='济南分公司开发部', - sort=5, - leader='就眠仪式', - phone='12312345679', - email='123qq.com', - status=1, - remark='测试', - create_at=now_time - - ), - Dept( - id=8, - parent_id=5, - dept_name='唐山测试部', - sort=5, - leader='mkg', - phone='12312345679', - email='123qq.com', - status=1, - remark='测试部', - create_at=now_time - - ) -] +# deptdata = [ +# Dept( +# id=1, +# parent_id=0, +# dept_name='总公司', +# sort=1, +# leader='就眠仪式', +# phone='12312345679', +# email='123qq.com', +# status=1, +# remark='这是总公司', +# create_at=now_time +# ), +# Dept( +# id=4, +# parent_id=1, +# dept_name='济南分公司', +# sort=2, +# leader='就眠仪式', +# phone='12312345679', +# email='123qq.com', +# status=1, +# remark='这是济南', +# create_at=now_time + +# ), +# Dept( +# id=5, +# parent_id=1, +# dept_name='唐山分公司', +# sort=4, +# leader='mkg', +# phone='12312345679', +# email='123qq.com', +# status=1, +# remark='这是唐山', +# create_at=now_time + +# ), +# Dept( +# id=7, +# parent_id=4, +# dept_name='济南分公司开发部', +# sort=5, +# leader='就眠仪式', +# phone='12312345679', +# email='123qq.com', +# status=1, +# remark='测试', +# create_at=now_time + +# ), +# Dept( +# id=8, +# parent_id=5, +# dept_name='唐山测试部', +# sort=5, +# leader='mkg', +# phone='12312345679', +# email='123qq.com', +# status=1, +# remark='测试部', +# create_at=now_time + +# ) +# ] powerdata = [ Power( id=1, @@ -562,8 +562,8 @@ def init_db(): print("加载系统必须用户数据") db.session.add_all(roledata) print("加载系统必须角色数据") - db.session.add_all(deptdata) - print("加载系统必须部门数据") + # db.session.add_all(deptdata) + # print("加载系统必须部门数据") db.session.add_all(powerdata) print("加载系统必须权限数据") db.session.commit() diff --git a/applications/common/utils/cache.py b/applications/common/utils/cache.py new file mode 100644 index 0000000000000000000000000000000000000000..1e8b6b533b67196a83f548eec71969f66ba84242 --- /dev/null +++ b/applications/common/utils/cache.py @@ -0,0 +1,22 @@ +from flask_caching import Cache + +#use : from applications.common.utils.cache import cache +cache = Cache() + +# 基于config实现,或者基于自己的业务情况实现 +def init_cache(app): + cache.init_app(app) + +# def __getattr__(self, name): +# return getattr(self._redis_client, name) + +# def __getitem__(self, name): +# return self._redis_client[name] + +# def __setitem__(self, name, value): +# self._redis_client[name] = value + +# def __delitem__(self, name): +# del self._redis_client[name] + + diff --git a/applications/common/utils/http.py b/applications/common/utils/http.py index 680df5fc336e3a1895816ef2d7f24a79a9cca291..84c8172f3b6f2658fdb9d69e97c0e52edd80efe6 100644 --- a/applications/common/utils/http.py +++ b/applications/common/utils/http.py @@ -1,14 +1,16 @@ from flask import jsonify -def success_api(msg: str = "成功"): +def success_api(msg: str = "成功",info=None): """ 成功响应 默认值“成功” """ - return jsonify(success=True, msg=msg) + if info: + return jsonify(success=True, msg=msg,info=info) + else: + return jsonify(success=True, msg=msg) - -def fail_api(msg: str = "失败"): +def fail_api(msg: str = "失败",code:int = 200): """ 失败响应 默认值“失败” """ - return jsonify(success=False, msg=msg) + return jsonify(success=False, msg=msg),code def table_api(msg: str = "", count=0, data=None, limit=10): diff --git a/applications/common/utils/rights.py b/applications/common/utils/rights.py index edd857f1b3fe0f48bbe1e992bc7cdea7aba1a8d9..d1addb4412453dab2630c75efd9d41f475d7e768 100644 --- a/applications/common/utils/rights.py +++ b/applications/common/utils/rights.py @@ -1,8 +1,9 @@ from functools import wraps -from flask import abort, request, jsonify, session, current_app -from flask_login import login_required, current_user +from flask import abort, request, current_app from applications.common.admin_log import admin_log - +from flask_jwt_extended import jwt_required, current_user +from applications.common.utils.cache import cache +from applications.common.utils.http import fail_api def authorize(power: str, log: bool = False): """用户权限判断,用于判断目前会话用户是否拥有访问权限 @@ -12,20 +13,24 @@ def authorize(power: str, log: bool = False): :param log: 是否记录日志, defaults to False :type log: bool, optional """ + def decorator(func): - @login_required + @jwt_required() @wraps(func) def wrapper(*args, **kwargs): # 定义管理员的id为1 if current_user.username == current_app.config.get("SUPERADMIN"): return func(*args, **kwargs) - if not power in session.get('permissions'): + + if (cache.get("permissions_" + str(current_user.id)) == None) or ( + not power in cache.get("permissions_" + str(current_user.id)) + ): if log: admin_log(request=request, is_access=False) - if request.method == 'GET': + if request.method == "GET": abort(403) else: - return jsonify(success=False, msg="权限不足!") + return fail_api(msg="权限不足!",code=403) if log: admin_log(request=request, is_access=True) return func(*args, **kwargs) @@ -33,3 +38,22 @@ def authorize(power: str, log: bool = False): return wrapper return decorator + + +# @auth.verify_token +# def verify_token(token): +# g.user = None +# serializer = Serializer(current_app.config.get("SECRET_KEY"), expires_in=current_app.config.get("TOKEN_EXPIRATION")) +# try: +# data = serializer.loads(token) +# # except BadSignature: +# # # AuthFailed 自定义的异常类型 +# # raise AuthFailed(msg='token不正确') +# # except SignatureExpired: +# # raise AuthFailed(msg='token过期') +# except: +# return False +# if 'username' in data: +# g.user = data['username'] +# return True +# return False diff --git a/applications/config.py b/applications/config.py index 387bbafa2f19a9586c95f403058eb3db962d0703..dfa0c48374fca7837ffeb8abeb99f7e8a0394084 100644 --- a/applications/config.py +++ b/applications/config.py @@ -1,27 +1,27 @@ import logging from urllib.parse import quote_plus as urlquote - +from datetime import timedelta class BaseConfig: SUPERADMIN = 'admin' - SYSTEM_NAME = 'Pear Admin' + SYSTEM_NAME = 'hml admin' # 主题面板的链接列表配置 SYSTEM_PANEL_LINKS = [ { "icon": "layui-icon layui-icon-auz", "title": "官方网站", - "href": "http://www.pearadmin.com" + "href": "/" }, { "icon": "layui-icon layui-icon-auz", "title": "开发文档", - "href": "http://www.pearadmin.com" + "href": "/" }, { "icon": "layui-icon layui-icon-auz", "title": "开源地址", - "href": "https://gitee.com/Jmysy/Pear-Admin-Layui" + "href": "/" } ] @@ -32,18 +32,51 @@ class BaseConfig: # JSON配置 JSON_AS_ASCII = False - SECRET_KEY = "pear-admin-flask" + SECRET_KEY = "hml-session-sec-key" # session用的是这个key #等替换了cache之后再删除 + JWT_SECRET_KEY = "hml-session-sec-key" + # JWT_TOKEN_EXPIRATION=60 #60=1min + JWT_ACCESS_TOKEN_EXPIRES = timedelta(minutes=60) # 设置默认的过期时间 + # mysql 配置 MYSQL_USERNAME = "root" - MYSQL_PASSWORD = "123456" - MYSQL_HOST = "127.0.0.1" + MYSQL_PASSWORD = "Brr0qZo6uo#6" + MYSQL_HOST = "121.5.62.78" MYSQL_PORT = 3306 MYSQL_DATABASE = "PearAdminFlask" # mysql 数据库的配置信息 SQLALCHEMY_DATABASE_URI = f"mysql+pymysql://{MYSQL_USERNAME}:{urlquote(MYSQL_PASSWORD)}@{MYSQL_HOST}:{MYSQL_PORT}/{MYSQL_DATABASE}?charset=utf8mb4" + # 下面五个参数是所有的类型共有的 + CACHE_NO_NULL_WARNING = "warning" # null类型时的警告消息 + CACHE_ARGS = [] # 在缓存类实例化过程中解包和传递的可选列表,用来配置相关后端的额外的参数 + CACHE_OPTIONS = {} # 可选字典,在缓存类实例化期间传递,也是用来配置相关后端的额外的键值对参数 + CACHE_DEFAULT_TIMEOUT = 3600*24 # 默认过期/超时时间,单位为秒 + # CACHE_THRESHOLD= # 缓存的最大条目数 + + CACHE_TYPE = 'SimpleCache' # 使用本地python字典进行存储,线程非安全 + + # CACHE_TYPE = 'filesystem' # 使用文件系统来存储缓存的值 + # CACHE_DIR = "" # 文件目录 + + # CACHE_TYPE = 'memcached' # 使用memcached服务器缓存 + # CACHE_KEY_PREFIX # 设置cache_key的前缀 + # CAHCE_MEMCACHED_SERVERS # 服务器地址的列表或元组 + # CACHE_MEMCACHED_USERNAME # 用户名 + # CACHE_MEMCACHED_PASSWORD # 密码 + + # CACHE_TYPE = 'uwsgi' # 使用uwsgi服务器作为缓存 + # CACHE_UWSGI_NAME # 要连接的uwsgi缓存实例的名称 + + # CACHE_TYPE = 'redis' # 使用redis作为缓存 + # CACHE_KEY_PREFIX # 设置cache_key的前缀 + # CACHE_REDIS_HOST # redis地址 + # CACHE_REDIS_PORT # redis端口 + # CACHE_REDIS_PASSWORD # redis密码 + # CACHE_REDIS_DB # 使用哪个数据库 + + # 默认日志等级 LOG_LEVEL = logging.WARN # flask-mail配置 diff --git a/applications/extensions/__init__.py b/applications/extensions/__init__.py index 7a1a3788039c74513bafa1c1e5b306d62197c3d9..e1b496bdcceabf6acba7748033613d883eeca6e4 100644 --- a/applications/extensions/__init__.py +++ b/applications/extensions/__init__.py @@ -7,10 +7,14 @@ from .init_error_views import init_error_views from .init_mail import init_mail, mail as flask_mail from .init_upload import init_upload from .init_migrate import init_migrate - +from .init_jwt import register_jwt +from .init_cache import register_cache def init_plugs(app: Flask) -> None: init_login_manager(app) + register_jwt(app) # 初始化登录的 jwt + # cache = register_cache(app) + register_cache(app) init_databases(app) init_template_directives(app) init_error_views(app) diff --git a/applications/extensions/init_cache.py b/applications/extensions/init_cache.py new file mode 100644 index 0000000000000000000000000000000000000000..1bf8e7ffe42778c84d18d30fd01c454c58f0ad77 --- /dev/null +++ b/applications/extensions/init_cache.py @@ -0,0 +1,7 @@ + +from flask import Flask +from applications.common.utils.cache import init_cache + +def register_cache(app: Flask): + init_cache(app) + \ No newline at end of file diff --git a/applications/extensions/init_jwt.py b/applications/extensions/init_jwt.py new file mode 100644 index 0000000000000000000000000000000000000000..0aa0497c5f575ca45f3312204051d55aaae89c27 --- /dev/null +++ b/applications/extensions/init_jwt.py @@ -0,0 +1,44 @@ +from flask import Flask, redirect, request,abort,jsonify +from flask_jwt_extended import JWTManager +from applications.common.utils.http import fail_api +from applications.common.utils.cache import cache +from applications.models.admin_user import UserCacheInfo + +jwt = JWTManager() + +def register_jwt(app: Flask): + from applications.models import User + + # app.config["JWT_SECRET_KEY"]="" # 已经写到配置文件里了 + + jwt.init_app(app) # flask 使用 jwt(三):flask-jwt-extended 使用 https://juejin.cn/post/7234450312726691898 + + # 注册一个回调函数,在访问受保护的路由时从数据库自动加载用户(current_user)。 + # 这应该在成功查找时返回任何 python 对象,或者如果查找因任何原因失败(例如,如果用户已从数据库中删除)则返回 None。 + @jwt.user_lookup_loader + def user_lookup_callback(_jwt_header, jwt_data): + identity = jwt_data["sub"] # userId + userinfo = cache.get("current_user_" + str(identity)) + if userinfo != None: + return userinfo + else: + # 查缓存是否存在,存在就拿缓存,不存在就读数据库并缓存 + user = User.query.filter_by(id=identity).one_or_none() + userinfo = UserCacheInfo(user.id,user.username) + cache.set("current_user_" + str(user.id), userinfo) + + return userinfo + + # 注册一个回调函数,该函数在使用 create_access_token 创建 JWT 时将传入的任何对象作为身份,并将其转换为 JSON 可序列化格式。 + @jwt.user_identity_loader + def user_identity_lookup(user): + return user.id + + @jwt.expired_token_loader + def my_expired_token_callback(jwt_header, jwt_payload): + if request.method == "GET": + return redirect("/passport/login") + + return fail_api(msg="token 已失效",code=401) + + diff --git a/applications/extensions/init_template_directives.py b/applications/extensions/init_template_directives.py index 86eda395ea5abff8a690cb988bb210b238909f6d..f6c76fef5be9e4caf98e9cfa23659b9bce29e5b2 100644 --- a/applications/extensions/init_template_directives.py +++ b/applications/extensions/init_template_directives.py @@ -1,11 +1,13 @@ from flask import session, current_app -from flask_login import current_user - +# from flask_login import current_user +from flask_jwt_extended import current_user +from applications.common.utils.cache import cache def init_template_directives(app): @app.template_global() def authorize(power): if current_user.username != current_app.config.get("SUPERADMIN"): - return bool(power in session.get('permissions')) + + return bool(power in cache.get("permissions_" + str(current_user.id))) else: return True diff --git a/applications/models/__init__.py b/applications/models/__init__.py index d94b26539de13d4ef34542987f64fd1d72d236a3..1667340118fde2550322bfbc51c96ea4f2c11ee8 100644 --- a/applications/models/__init__.py +++ b/applications/models/__init__.py @@ -1,4 +1,4 @@ -from .admin_dept import Dept +# from .admin_dept import Dept from .admin_dict import DictType, DictData from .admin_log import AdminLog from .admin_photo import Photo @@ -6,5 +6,6 @@ from .admin_power import Power from .admin_role import Role from .admin_role_power import role_power from .admin_user import User +from .admin_user import UserCacheInfo from .admin_user_role import user_role from .admin_mail import Mail diff --git a/applications/models/admin_dept.py b/applications/models/admin_dept.py index 7ecb51665702e2ac2db4d0021532325183546348..fedf528f6db08427fcaf912625d2b623af001d10 100644 --- a/applications/models/admin_dept.py +++ b/applications/models/admin_dept.py @@ -1,18 +1,18 @@ -import datetime -from applications.extensions import db +# import datetime +# from applications.extensions import db -class Dept(db.Model): - __tablename__ = 'admin_dept' - id = db.Column(db.Integer, primary_key=True, comment="部门ID") - parent_id = db.Column(db.Integer, comment="父级编号") - dept_name = db.Column(db.String(50), comment="部门名称") - sort = db.Column(db.Integer, comment="排序") - leader = db.Column(db.String(50), comment="负责人") - phone = db.Column(db.String(20), comment="联系方式") - email = db.Column(db.String(50), comment="邮箱") - status = db.Column(db.Integer, comment='状态(1开启,0关闭)') - remark = db.Column(db.Text, comment="备注") - address = db.Column(db.String(255), comment="详细地址") - create_at = db.Column(db.DateTime, default=datetime.datetime.now, comment='创建时间') - update_at = db.Column(db.DateTime, default=datetime.datetime.now, onupdate=datetime.datetime.now, comment='创建时间') \ No newline at end of file +# class Dept(db.Model): +# __tablename__ = 'admin_dept' +# id = db.Column(db.Integer, primary_key=True, comment="部门ID") +# parent_id = db.Column(db.Integer, comment="父级编号") +# dept_name = db.Column(db.String(50), comment="部门名称") +# sort = db.Column(db.Integer, comment="排序") +# leader = db.Column(db.String(50), comment="负责人") +# phone = db.Column(db.String(20), comment="联系方式") +# email = db.Column(db.String(50), comment="邮箱") +# status = db.Column(db.Integer, comment='状态(1开启,0关闭)') +# remark = db.Column(db.Text, comment="备注") +# address = db.Column(db.String(255), comment="详细地址") +# create_at = db.Column(db.DateTime, default=datetime.datetime.now, comment='创建时间') +# update_at = db.Column(db.DateTime, default=datetime.datetime.now, onupdate=datetime.datetime.now, comment='创建时间') \ No newline at end of file diff --git a/applications/models/admin_user.py b/applications/models/admin_user.py index e8e278f6055a60042fe328cc84b25ef9cf122196..da9b6f5b2971702939469ae2268fabcba45f6bdd 100644 --- a/applications/models/admin_user.py +++ b/applications/models/admin_user.py @@ -1,10 +1,10 @@ import datetime -from flask_login import UserMixin +# from flask_login import UserMixin from werkzeug.security import generate_password_hash, check_password_hash from applications.extensions import db -class User(db.Model, UserMixin): +class User(db.Model): __tablename__ = 'admin_user' id = db.Column(db.Integer, primary_key=True, autoincrement=True, comment='用户ID') username = db.Column(db.String(20), comment='用户名') @@ -23,3 +23,16 @@ class User(db.Model, UserMixin): def validate_password(self, password): return check_password_hash(self.password_hash, password) + + +# 用户简单存储的临时数据格式 +class UserCacheInfo: + + username:str + id:int + + def __init__(self,id,username) -> None: + self.id=id + self.username=username + + diff --git a/applications/view/__init__.py b/applications/view/__init__.py index 6b5cf78b6fe07f81df34aeba4829e5a1639a64d5..e0dbf66cc16e0547fe76d67f2f7ebc1c3bab0664 100644 --- a/applications/view/__init__.py +++ b/applications/view/__init__.py @@ -2,7 +2,7 @@ from applications.view.admin import register_admin_views from applications.view.index import register_index_views from applications.view.passport import register_passport_views from applications.view.rights import register_rights_view -from applications.view.department import register_dept_views +# from applications.view.department import register_dept_views from applications.view.plugin import register_plugin_views def init_view(app): @@ -10,5 +10,5 @@ def init_view(app): register_index_views(app) register_rights_view(app) register_passport_views(app) - register_dept_views(app) + # register_dept_views(app) register_plugin_views(app) diff --git a/applications/view/admin/user.py b/applications/view/admin/user.py index 30a6bd1c2c4b5a69e7bf3d5eab9f9367b58c150d..de8eec3b8e2aaf52d2c134d9704ef0e9c081cf87 100644 --- a/applications/view/admin/user.py +++ b/applications/view/admin/user.py @@ -1,5 +1,5 @@ -from flask import Blueprint, render_template, request, session -from flask_login import login_required, current_user +from flask import Blueprint, render_template, request +from flask_login import login_required from sqlalchemy import desc from applications.common import curd @@ -8,9 +8,11 @@ from applications.common.utils.http import table_api, fail_api, success_api from applications.common.utils.rights import authorize from applications.common.utils.validate import str_escape from applications.extensions import db -from applications.models import Role, Dept +from applications.models import Role from applications.models import User, AdminLog +from flask_jwt_extended import current_user + admin_user = Blueprint('adminUser', __name__, url_prefix='/admin/user') @@ -18,6 +20,8 @@ admin_user = Blueprint('adminUser', __name__, url_prefix='/admin/user') @admin_user.get('/') @authorize("admin:user:main") def main(): + # current_user2 = get_jwt_identity() + # c3= current_user return render_template('admin/user/main.html') @@ -29,21 +33,24 @@ def data(): real_name = str_escape(request.args.get('realName', type=str)) username = str_escape(request.args.get('username', type=str)) - dept_id = request.args.get('deptId', type=int) + # dept_id = request.args.get('deptId', type=int) filters = [] if real_name: filters.append(User.realname.contains(real_name)) if username: filters.append(User.realname.contains(username)) - if dept_id: - filters.append(User.realname == dept_id) + # if dept_id: + # filters.append(User.realname == dept_id) # print(*filters) + # query = db.session.query( + # User, + # Dept + # ).filter(*filters).outerjoin(Dept, User.dept_id == Dept.id).layui_paginate() query = db.session.query( - User, - Dept - ).filter(*filters).outerjoin(Dept, User.dept_id == Dept.id).layui_paginate() + User + ).filter(*filters).layui_paginate() return table_api( data=[{ @@ -52,14 +59,11 @@ def data(): 'realname': user.realname, 'enable': user.enable, 'create_at': user.create_at, - 'update_at': user.update_at, - 'dept_name': dept.dept_name if dept else None - } for user, dept in query.items], + 'update_at': user.update_at + } for user in query.items], count=query.total) - # 用户增加 - - +# 用户增加 @admin_user.get('/add') @authorize("admin:user:add", log=True) def add(): @@ -127,9 +131,9 @@ def update(): id = str_escape(req_json.get("userId")) username = str_escape(req_json.get('username')) real_name = str_escape(req_json.get('realName')) - dept_id = str_escape(req_json.get('deptId')) + # dept_id = str_escape(req_json.get('deptId')) role_ids = a.split(',') - User.query.filter_by(id=id).update({'username': username, 'realname': real_name, 'dept_id': dept_id}) + User.query.filter_by(id=id).update({'username': username, 'realname': real_name}) u = User.query.filter_by(id=id).first() roles = Role.query.filter(Role.id.in_(role_ids)).all() @@ -247,8 +251,8 @@ def batch_remove(): return success_api(msg="批量删除成功") -@admin_user.get("test") -def test(): - print(session) - print(session.get('role')[0]) - return '6' +# @admin_user.get("test") +# def test(): +# print(session) +# print(session.get('role')[0]) +# return '6' diff --git a/applications/view/department/__init__.py b/applications/view/department/__init__.py index 82abac35c2967ad7c0c16198ca3fab89e8084a9d..a1c2cbfc986072738834ea284cf9f25a2601ac80 100644 --- a/applications/view/department/__init__.py +++ b/applications/view/department/__init__.py @@ -1,144 +1,144 @@ -from flask import Blueprint, render_template, request, jsonify - -from applications.common import curd -from applications.common.utils import validate -from applications.common.utils.http import success_api, fail_api -from applications.common.utils.rights import authorize -from applications.common.utils.validate import str_escape -from applications.extensions import db -from applications.models import Dept, User -from applications.schemas import DeptOutSchema - -dept_bp = Blueprint('dept', __name__, url_prefix='/dept') - - -def register_dept_views(app): - app.register_blueprint(dept_bp) - - -@dept_bp.get('/') -@authorize("admin:dept:main", log=True) -def main(): - return render_template('admin/dept/main.html') - - -@dept_bp.post('/data') -@authorize("admin:dept:main", log=True) -def data(): - dept = Dept.query.order_by(Dept.sort).all() - power_data = curd.model_to_dicts(schema=DeptOutSchema, data=dept) - res = { - "data": power_data - } - return jsonify(res) - - -@dept_bp.get('/add') -@authorize("admin:dept:add", log=True) -def add(): - return render_template('admin/dept/add.html') - - -@dept_bp.get('/tree') -@authorize("admin:dept:main", log=True) -def tree(): - dept = Dept.query.order_by(Dept.sort).all() - power_data = curd.model_to_dicts(schema=DeptOutSchema, data=dept) - res = { - "status": {"code": 200, "message": "默认"}, - "data": power_data - - } - return jsonify(res) - - -@dept_bp.post('/save') -@authorize("admin:dept:add", log=True) -def save(): - req_json = request.get_json(force=True) - dept = Dept( - parent_id=req_json.get('parentId'), - dept_name=str_escape(req_json.get('deptName')), - sort=str_escape(req_json.get('sort')), - leader=str_escape(req_json.get('leader')), - phone=str_escape(req_json.get('phone')), - email=str_escape(req_json.get('email')), - status=str_escape(req_json.get('status')), - address=str_escape(req_json.get('address')) - ) - r = db.session.add(dept) - db.session.commit() - return success_api(msg="成功") - - -@dept_bp.get('/edit') -@authorize("admin:dept:edit", log=True) -def edit(): - _id = request.args.get("deptId") - dept = curd.get_one_by_id(model=Dept, id=_id) - return render_template('admin/dept/edit.html', dept=dept) - - -# 启用 -@dept_bp.put('/enable') -@authorize("admin:dept:edit", log=True) -def enable(): - id = request.get_json(force=True).get('deptId') - if id: - enable = 1 - d = Dept.query.filter_by(id=id).update({"status": enable}) - if d: - db.session.commit() - return success_api(msg="启用成功") - return fail_api(msg="出错啦") - return fail_api(msg="数据错误") - - -# 禁用 -@dept_bp.put('/disable') -@authorize("admin:dept:edit", log=True) -def dis_enable(): - id = request.get_json(force=True).get('deptId') - if id: - enable = 0 - d = Dept.query.filter_by(id=id).update({"status": enable}) - if d: - db.session.commit() - return success_api(msg="禁用成功") - return fail_api(msg="出错啦") - return fail_api(msg="数据错误") - - -@dept_bp.put('/update') -@authorize("admin:dept:edit", log=True) -def update(): - json = request.get_json(force=True) - id = json.get("deptId"), - data = { - "dept_name": validate.str_escape(json.get("deptName")), - "sort": validate.str_escape(json.get("sort")), - "leader": validate.str_escape(json.get("leader")), - "phone": validate.str_escape(json.get("phone")), - "email": validate.str_escape(json.get("email")), - "status": validate.str_escape(json.get("status")), - "address": validate.str_escape(json.get("address")) - } - d = Dept.query.filter_by(id=id).update(data) - if not d: - return fail_api(msg="更新失败") - db.session.commit() - return success_api(msg="更新成功") - - -@dept_bp.delete('/remove/') -@authorize("admin:dept:remove", log=True) -def remove(_id): - d = Dept.query.filter_by(id=_id).delete() - if not d: - return fail_api(msg="删除失败") - res = User.query.filter_by(dept_id=_id).update({"dept_id": None}) - db.session.commit() - if res: - return success_api(msg="删除成功") - else: - return fail_api(msg="删除失败") +# from flask import Blueprint, render_template, request, jsonify + +# from applications.common import curd +# from applications.common.utils import validate +# from applications.common.utils.http import success_api, fail_api +# from applications.common.utils.rights import authorize +# from applications.common.utils.validate import str_escape +# from applications.extensions import db +# from applications.models import Dept, User +# from applications.schemas import DeptOutSchema + +# dept_bp = Blueprint('dept', __name__, url_prefix='/dept') + + +# def register_dept_views(app): +# app.register_blueprint(dept_bp) + + +# @dept_bp.get('/') +# @authorize("admin:dept:main", log=True) +# def main(): +# return render_template('admin/dept/main.html') + + +# @dept_bp.post('/data') +# @authorize("admin:dept:main", log=True) +# def data(): +# dept = Dept.query.order_by(Dept.sort).all() +# power_data = curd.model_to_dicts(schema=DeptOutSchema, data=dept) +# res = { +# "data": power_data +# } +# return jsonify(res) + + +# @dept_bp.get('/add') +# @authorize("admin:dept:add", log=True) +# def add(): +# return render_template('admin/dept/add.html') + + +# @dept_bp.get('/tree') +# @authorize("admin:dept:main", log=True) +# def tree(): +# dept = Dept.query.order_by(Dept.sort).all() +# power_data = curd.model_to_dicts(schema=DeptOutSchema, data=dept) +# res = { +# "status": {"code": 200, "message": "默认"}, +# "data": power_data + +# } +# return jsonify(res) + + +# @dept_bp.post('/save') +# @authorize("admin:dept:add", log=True) +# def save(): +# req_json = request.get_json(force=True) +# dept = Dept( +# parent_id=req_json.get('parentId'), +# dept_name=str_escape(req_json.get('deptName')), +# sort=str_escape(req_json.get('sort')), +# leader=str_escape(req_json.get('leader')), +# phone=str_escape(req_json.get('phone')), +# email=str_escape(req_json.get('email')), +# status=str_escape(req_json.get('status')), +# address=str_escape(req_json.get('address')) +# ) +# r = db.session.add(dept) +# db.session.commit() +# return success_api(msg="成功") + + +# @dept_bp.get('/edit') +# @authorize("admin:dept:edit", log=True) +# def edit(): +# _id = request.args.get("deptId") +# dept = curd.get_one_by_id(model=Dept, id=_id) +# return render_template('admin/dept/edit.html', dept=dept) + + +# # 启用 +# @dept_bp.put('/enable') +# @authorize("admin:dept:edit", log=True) +# def enable(): +# id = request.get_json(force=True).get('deptId') +# if id: +# enable = 1 +# d = Dept.query.filter_by(id=id).update({"status": enable}) +# if d: +# db.session.commit() +# return success_api(msg="启用成功") +# return fail_api(msg="出错啦") +# return fail_api(msg="数据错误") + + +# # 禁用 +# @dept_bp.put('/disable') +# @authorize("admin:dept:edit", log=True) +# def dis_enable(): +# id = request.get_json(force=True).get('deptId') +# if id: +# enable = 0 +# d = Dept.query.filter_by(id=id).update({"status": enable}) +# if d: +# db.session.commit() +# return success_api(msg="禁用成功") +# return fail_api(msg="出错啦") +# return fail_api(msg="数据错误") + + +# @dept_bp.put('/update') +# @authorize("admin:dept:edit", log=True) +# def update(): +# json = request.get_json(force=True) +# id = json.get("deptId"), +# data = { +# "dept_name": validate.str_escape(json.get("deptName")), +# "sort": validate.str_escape(json.get("sort")), +# "leader": validate.str_escape(json.get("leader")), +# "phone": validate.str_escape(json.get("phone")), +# "email": validate.str_escape(json.get("email")), +# "status": validate.str_escape(json.get("status")), +# "address": validate.str_escape(json.get("address")) +# } +# d = Dept.query.filter_by(id=id).update(data) +# if not d: +# return fail_api(msg="更新失败") +# db.session.commit() +# return success_api(msg="更新成功") + + +# @dept_bp.delete('/remove/') +# @authorize("admin:dept:remove", log=True) +# def remove(_id): +# d = Dept.query.filter_by(id=_id).delete() +# if not d: +# return fail_api(msg="删除失败") +# res = User.query.filter_by(dept_id=_id).update({"dept_id": None}) +# db.session.commit() +# if res: +# return success_api(msg="删除成功") +# else: +# return fail_api(msg="删除失败") diff --git a/applications/view/passport/__init__.py b/applications/view/passport/__init__.py index e5a7c97a34810ec477cc8ed5b18f641c8207a824..e536c95174ea6dd825963b49f891cfeedcac97f0 100644 --- a/applications/view/passport/__init__.py +++ b/applications/view/passport/__init__.py @@ -1,12 +1,25 @@ -from flask import Blueprint, session, redirect, url_for, render_template, request +from flask import ( + Blueprint, + session, + redirect, + url_for, + render_template, + request, + current_app, +) from flask_login import current_user, login_user, login_required, logout_user from applications.common import admin as index_curd from applications.common.admin_log import login_log from applications.common.utils.http import fail_api, success_api from applications.models import User +from applications.models import UserCacheInfo -passport_bp = Blueprint('passport', __name__, url_prefix='/passport') +# from itsdangerous import TimedJSONWebSignatureSerializer as Serializer +from flask_jwt_extended import create_access_token, create_refresh_token +from applications.common.utils.cache import cache + +passport_bp = Blueprint("passport", __name__, url_prefix="/passport") def register_passport_views(app): @@ -14,7 +27,7 @@ def register_passport_views(app): # 获取验证码 -@passport_bp.get('/getCaptcha') +@passport_bp.get("/getCaptcha") def get_captcha(): resp, code = index_curd.get_captcha() session["code"] = code @@ -22,31 +35,31 @@ def get_captcha(): # 登录 -@passport_bp.get('/login') +@passport_bp.get("/login") def login(): if current_user.is_authenticated: - return redirect(url_for('admin.index')) - return render_template('admin/login.html') + return redirect(url_for("admin.index")) + return render_template("admin/login.html") # 登录 -@passport_bp.post('/login') +@passport_bp.post("/login") def login_post(): req = request.form - username = req.get('username') - password = req.get('password') - code = req.get('captcha').__str__().lower() + username = req.get("username") + password = req.get("password") + code = req.get("captcha").__str__().lower() if not username or not password or not code: return fail_api(msg="用户名或密码没有输入") s_code = session.get("code", None) session["code"] = None - if not all([code, s_code]): - return fail_api(msg="参数错误") + # if not all([code, s_code]): + # return fail_api(msg="参数错误") - if code != s_code: - return fail_api(msg="验证码错误") + # if code != s_code: + # return fail_api(msg="验证码错误") user = User.query.filter_by(username=username).first() if not user: @@ -57,35 +70,56 @@ def login_post(): if username == user.username and user.validate_password(password): # 登录 - login_user(user) + # login_user(user) + + # 生成token + access_token = create_access_token(identity=user) + refresh_token = create_refresh_token(identity=user) + + # 生成好token需要返回给前端存储起来 + # from applications.common.utils.cache import cache + # cache.set("AAA","666y") + # 记录登录日志 login_log(request, uid=user.id, is_access=True) - # 授权路由存入session - role = current_user.role + # # 授权路由存入session + role = user.role user_power = [] for i in role: if i.enable == 0: continue for p in i.power: - if p.enable == 0: + if p.enable == 0 or p.code == "": continue user_power.append(p.code) - session['permissions'] = user_power + + cache.set("permissions_" + str(user.id), user_power) + + # current_user 也缓存起来 + userinfo = UserCacheInfo(user.id,user.username) + + cache.set("current_user_" + str(user.id), userinfo) + # session['permissions'] = user_power # # 角色存入session # roles = [] # for role in current_user.role.all(): # roles.append(role.id) # session['role'] = [roles] - return success_api(msg="登录成功") + result={ + "access_token":access_token, + "refresh_token":refresh_token + } + + return success_api(msg="登录成功",info=result) login_log(request, uid=user.id, is_access=False) return fail_api(msg="用户名或密码错误") # 退出登录 -@passport_bp.post('/logout') +@passport_bp.post("/logout") @login_required def logout(): logout_user() - session.pop('permissions') + session.pop("permissions") return success_api(msg="注销成功") diff --git a/plugins/helloworld/templates/helloworld_index.html b/plugins/helloworld/templates/helloworld_index.html index 0982b2448d51d22dc2d61716a4c8bdb68b750f8a..67cdff6341a7bec1f4647152ae67ef4b222b020e 100644 --- a/plugins/helloworld/templates/helloworld_index.html +++ b/plugins/helloworld/templates/helloworld_index.html @@ -3,7 +3,7 @@ pear-admin-flask - + {% include 'admin/common/header.html' %} diff --git a/plugins/replacePage/templates/replacePage_index.html b/plugins/replacePage/templates/replacePage_index.html index 06d8e06c314ea521be543ff5f9c92f3486501ac4..ca3e0366d93c0df0d2a73d856e145a469f7a36dc 100644 --- a/plugins/replacePage/templates/replacePage_index.html +++ b/plugins/replacePage/templates/replacePage_index.html @@ -3,7 +3,7 @@ pear-admin-flask - + {% include 'admin/common/header.html' %} diff --git a/requirements.txt b/requirements.txt index 34a80f2423a3363050c8730eb3f3e2793b0449c5..9ce0b129d00201df08b3d90ac5fcafaf43fcb73d 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,7 +1,11 @@ Flask Flask-APScheduler Flask-Migrate -Flask-Login +# Flask-Login +# itsdangerous #弃用 +flask-jwt-extended +# flask-httpauth +flask_caching Flask_Reuploaded Flask-SQLAlchemy flask-marshmallow @@ -11,4 +15,4 @@ psutil Flask-Mail Pillow validators -cryptography \ No newline at end of file +cryptography diff --git a/static/admin/admin/data/menu.json b/static/admin/admin/data/menu.json index 3a20b6e414bc033779d9682016af1608292b8275..1d7bd09158952301d2b7e31a4820bf22db257662 100644 --- a/static/admin/admin/data/menu.json +++ b/static/admin/admin/data/menu.json @@ -356,7 +356,6 @@ "openType": "_iframe", "href": "view/system/power.html" }, - { "id": 604, "title": "部门管理", diff --git a/templates/admin/index.html b/templates/admin/index.html index 94fff387ce49354a75a9ac5232027aea85b74137..3ede5838efea595196c22c6060f452a358bb3012 100644 --- a/templates/admin/index.html +++ b/templates/admin/index.html @@ -2,7 +2,7 @@ {% include 'admin/common/header.html' %} - Pear Admin Flask + hml admin @@ -31,7 +31,6 @@