refactor(重构程序&目录结构)
This commit is contained in:
@@ -1,26 +1,20 @@
|
||||
import os
|
||||
|
||||
from flask import Flask
|
||||
from applications.common.flask_uploads import configure_uploads
|
||||
from common.flask_uploads import configure_uploads
|
||||
|
||||
from applications.common.utils.upload import photos
|
||||
from applications.configs import common
|
||||
from applications.extensions import init_plugs
|
||||
from common.utils.upload import photos
|
||||
from extensions import init_plugs
|
||||
from applications.view import init_view
|
||||
from applications.api import init_api
|
||||
from applications.configs import config
|
||||
import config
|
||||
|
||||
|
||||
def create_app(config_name=None):
|
||||
def create_app():
|
||||
app = Flask('pear-admin-flask')
|
||||
|
||||
if not config_name:
|
||||
# 尝试从本地环境中读取
|
||||
config_name = os.getenv('FLASK_CONFIG', 'development')
|
||||
|
||||
# 引入数据库配置
|
||||
app.config.from_object(common)
|
||||
app.config.from_object(config[config_name])
|
||||
app.config.from_object(config)
|
||||
|
||||
# 注册各种插件
|
||||
init_plugs(app)
|
||||
|
||||
@@ -1,20 +1,19 @@
|
||||
from flask import jsonify
|
||||
from flask_restful import Resource, reqparse
|
||||
|
||||
from applications.common.utils.http import success_api, fail_api
|
||||
from applications.extensions import db
|
||||
from applications.models import CompanyDepartment, CompanyUser
|
||||
from common.utils.http import success_api, fail_api
|
||||
from extensions import db
|
||||
from models import DepartmentModels, UserModels
|
||||
|
||||
|
||||
class DepartmentsResource(Resource):
|
||||
|
||||
def get(self):
|
||||
dept_data = CompanyDepartment.query.order_by(CompanyDepartment.sort).all()
|
||||
dept_data = DepartmentModels.query.order_by(DepartmentModels.sort).all()
|
||||
# TODO dtree 需要返回状态信息
|
||||
res = {
|
||||
"status": {"code": 200, "message": "默认"},
|
||||
"data": [
|
||||
|
||||
{
|
||||
'deptId': item.id,
|
||||
'parentId': item.parent_id,
|
||||
@@ -45,7 +44,7 @@ class DepartmentsResource(Resource):
|
||||
|
||||
res = parser.parse_args()
|
||||
|
||||
dept = CompanyDepartment(
|
||||
dept = DepartmentModels(
|
||||
parent_id=res.parent_id,
|
||||
dept_name=res.dept_name,
|
||||
sort=res.sort,
|
||||
@@ -63,7 +62,7 @@ class DepartmentsResource(Resource):
|
||||
|
||||
class DepartmentResource(Resource):
|
||||
def get(self, dept_id):
|
||||
dept = CompanyDepartment.query.filter_by(id=dept_id).first()
|
||||
dept = DepartmentModels.query.filter_by(id=dept_id).first()
|
||||
dept_data = {
|
||||
'id': dept.id,
|
||||
'dept_name': dept.dept_name,
|
||||
@@ -96,15 +95,15 @@ class DepartmentResource(Resource):
|
||||
"status": res.status,
|
||||
"address": res.address
|
||||
}
|
||||
res = CompanyDepartment.query.filter_by(id=dept_id).update(data)
|
||||
res = DepartmentModels.query.filter_by(id=dept_id).update(data)
|
||||
if not res:
|
||||
return fail_api(message="更新失败")
|
||||
db.session.commit()
|
||||
return success_api(message="更新成功")
|
||||
|
||||
def delete(self, dept_id):
|
||||
ret = CompanyDepartment.query.filter_by(id=dept_id).delete()
|
||||
CompanyUser.query.filter_by(dept_id=dept_id).update({"dept_id": None})
|
||||
ret = DepartmentModels.query.filter_by(id=dept_id).delete()
|
||||
UserModels.query.filter_by(dept_id=dept_id).update({"dept_id": None})
|
||||
db.session.commit()
|
||||
if ret:
|
||||
return success_api(message="删除成功")
|
||||
@@ -113,7 +112,7 @@ class DepartmentResource(Resource):
|
||||
|
||||
class DeptEnableResource(Resource):
|
||||
def put(self, dept_id):
|
||||
d = CompanyDepartment.query.get(dept_id)
|
||||
d = DepartmentModels.query.get(dept_id)
|
||||
if d:
|
||||
d.status = not d.status
|
||||
db.session.commit()
|
||||
|
||||
@@ -5,9 +5,9 @@ from flask import request, jsonify, current_app
|
||||
from flask_login import current_user
|
||||
from flask_restful import Resource, reqparse
|
||||
|
||||
from applications.common.utils.http import success_api, fail_api
|
||||
from applications.extensions import db
|
||||
from applications.models import RightsPower, RightsRole
|
||||
from common.utils.http import success_api, fail_api
|
||||
from extensions import db
|
||||
from models import RightModels, RoleModels
|
||||
|
||||
|
||||
def get_render_config():
|
||||
@@ -105,7 +105,6 @@ def make_menu_tree():
|
||||
if p.type == 0 or p.type == 1:
|
||||
powers.append(p)
|
||||
|
||||
# power_dict = marshal(powers, RightsPower.fields2()) # 生成可序列化对象
|
||||
power_dict = [
|
||||
{
|
||||
'id': item.id,
|
||||
@@ -118,8 +117,6 @@ def make_menu_tree():
|
||||
'icon': item.icon,
|
||||
'sort': item.sort,
|
||||
'enable': item.enable,
|
||||
'update_at': item.update_at.strftime('%Y-%m-%d %H:%M:%S'),
|
||||
'create_at': item.create_at.strftime('%Y-%m-%d %H:%M:%S'),
|
||||
} for item in powers
|
||||
]
|
||||
power_dict.sort(key=lambda x: x['id'], reverse=True)
|
||||
@@ -143,15 +140,15 @@ def make_menu_tree():
|
||||
|
||||
# 删除权限(目前没有判断父节点自动删除子节点)
|
||||
def remove_power(power_id):
|
||||
power = RightsPower.query.filter_by(id=power_id).first()
|
||||
power = RightModels.query.filter_by(id=power_id).first()
|
||||
role_id_list = []
|
||||
roles = power.role
|
||||
for role in roles:
|
||||
role_id_list.append(role.id)
|
||||
roles = RightsRole.query.filter(RightsRole.id.in_(role_id_list)).all()
|
||||
roles = RoleModels.query.filter(RoleModels.id.in_(role_id_list)).all()
|
||||
for p in roles:
|
||||
power.role.remove(p)
|
||||
r = RightsPower.query.filter_by(id=power_id).delete()
|
||||
r = RightModels.query.filter_by(id=power_id).delete()
|
||||
db.session.commit()
|
||||
return r
|
||||
|
||||
@@ -177,8 +174,8 @@ class RightRightsResource(Resource):
|
||||
def get(self):
|
||||
"""获取选择父节点"""
|
||||
|
||||
power = RightsPower.query.all()
|
||||
# power_data = marshal(power, RightsPower.fields())
|
||||
power = RightModels.query.all()
|
||||
# power_data = marshal(power, RightModels.fields())
|
||||
power_data = [
|
||||
{
|
||||
'powerId': item.id,
|
||||
@@ -189,8 +186,6 @@ class RightRightsResource(Resource):
|
||||
'parentId': item.parent_id,
|
||||
'icon': item.icon,
|
||||
'sort': item.sort,
|
||||
'create_at': item.create_at.strftime('%Y-%m-%d %H:%M:%S'),
|
||||
'update_at': item.update_at.strftime('%Y-%m-%d %H:%M:%S'),
|
||||
'enable': item.enable,
|
||||
} for item in power
|
||||
]
|
||||
@@ -211,7 +206,7 @@ class RightPowerResource(Resource):
|
||||
|
||||
def post(self, power_id):
|
||||
res = parser_power.parse_args()
|
||||
power = RightsPower(
|
||||
power = RightModels(
|
||||
icon=res.icon,
|
||||
open_type=res.open_type,
|
||||
parent_id=res.parent_id,
|
||||
@@ -233,15 +228,15 @@ class RightPowerResource(Resource):
|
||||
|
||||
def delete(self, power_id):
|
||||
# 删除权限(目前没有判断父节点自动删除子节点)
|
||||
power = RightsPower.query.filter_by(id=power_id).first()
|
||||
power = RightModels.query.filter_by(id=power_id).first()
|
||||
role_id_list = []
|
||||
roles = power.role
|
||||
for role in roles:
|
||||
role_id_list.append(role.id)
|
||||
roles = RightsRole.query.filter(RightsRole.id.in_(role_id_list)).all()
|
||||
roles = RoleModels.query.filter(RoleModels.id.in_(role_id_list)).all()
|
||||
for p in roles:
|
||||
power.role.remove(p)
|
||||
r = RightsPower.query.filter_by(id=power_id).delete()
|
||||
r = RightModels.query.filter_by(id=power_id).delete()
|
||||
db.session.commit()
|
||||
|
||||
if r:
|
||||
@@ -262,7 +257,7 @@ class RightPowerResource(Resource):
|
||||
"url": res.power_url,
|
||||
"sort": res.sort
|
||||
}
|
||||
power = RightsPower.query.filter_by(id=power_id).update(data)
|
||||
power = RightModels.query.filter_by(id=power_id).update(data)
|
||||
db.session.commit()
|
||||
|
||||
if not power:
|
||||
@@ -273,7 +268,7 @@ class RightPowerResource(Resource):
|
||||
class RightPowerEnableResource(Resource):
|
||||
def put(self, right_id):
|
||||
|
||||
power = RightsPower.query.get(right_id)
|
||||
power = RightModels.query.get(right_id)
|
||||
if power:
|
||||
power.enable = not power.enable
|
||||
db.session.commit()
|
||||
|
||||
@@ -1,28 +1,28 @@
|
||||
from flask_restful import Resource, reqparse, marshal
|
||||
|
||||
from applications.common.utils.http import table_api, success_api, fail_api
|
||||
from applications.extensions import db
|
||||
from applications.models import RightsPower, RightsRole, CompanyUser
|
||||
from common.utils.http import table_api, success_api, fail_api
|
||||
from extensions import db
|
||||
from models import RightModels, RoleModels, UserModels
|
||||
|
||||
|
||||
def remove_role(role_id):
|
||||
""" 删除角色 """
|
||||
role = RightsRole.query.filter_by(id=role_id).first()
|
||||
role = RoleModels.query.filter_by(id=role_id).first()
|
||||
# 删除该角色的权限
|
||||
power_id_list = []
|
||||
for p in role.power:
|
||||
power_id_list.append(p.id)
|
||||
|
||||
powers = RightsPower.query.filter(RightsPower.id.in_(power_id_list)).all()
|
||||
powers = RightModels.query.filter(RightModels.id.in_(power_id_list)).all()
|
||||
for p in powers:
|
||||
role.power.remove(p)
|
||||
user_id_list = []
|
||||
for u in role.user:
|
||||
user_id_list.append(u.id)
|
||||
users = CompanyUser.query.filter(CompanyUser.id.in_(user_id_list)).all()
|
||||
users = UserModels.query.filter(UserModels.id.in_(user_id_list)).all()
|
||||
for u in users:
|
||||
role.user.remove(u)
|
||||
r = RightsRole.query.filter_by(id=role_id).delete()
|
||||
r = RoleModels.query.filter_by(id=role_id).delete()
|
||||
db.session.commit()
|
||||
return r
|
||||
|
||||
@@ -46,11 +46,11 @@ class RoleRolesResource(Resource):
|
||||
|
||||
filters = []
|
||||
if res.role_name:
|
||||
filters.append(RightsRole.name.like('%' + res.role_name + '%'))
|
||||
filters.append(RoleModels.name.like('%' + res.role_name + '%'))
|
||||
if res.role_code:
|
||||
filters.append(RightsRole.code.like('%' + res.role_code + '%'))
|
||||
filters.append(RoleModels.code.like('%' + res.role_code + '%'))
|
||||
|
||||
paginate = RightsRole.query.filter(*filters).paginate(page=res.page, per_page=res.limit, error_out=False)
|
||||
paginate = RoleModels.query.filter(*filters).paginate(page=res.page, per_page=res.limit, error_out=False)
|
||||
|
||||
return table_api(result={'items': [{'id': item.id,
|
||||
'roleName': item.name,
|
||||
@@ -59,7 +59,7 @@ class RoleRolesResource(Resource):
|
||||
'comment': item.comment,
|
||||
'details': item.details,
|
||||
'sort': item.sort,
|
||||
'create_at': str(item.create_at), } for item in paginate.items],
|
||||
} for item in paginate.items],
|
||||
'total': paginate.total}
|
||||
, code=0)
|
||||
|
||||
@@ -85,7 +85,7 @@ class RoleRoleResource(Resource):
|
||||
|
||||
res = parser.parse_args()
|
||||
|
||||
role = RightsRole(
|
||||
role = RoleModels(
|
||||
details=res.details,
|
||||
enable=res.enable,
|
||||
code=res.role_code,
|
||||
@@ -116,7 +116,7 @@ class RoleRoleResource(Resource):
|
||||
"details": res.details
|
||||
}
|
||||
|
||||
role = RightsRole.query.filter_by(id=role_id).update(data)
|
||||
role = RoleModels.query.filter_by(id=role_id).update(data)
|
||||
db.session.commit()
|
||||
if not role:
|
||||
return fail_api(message="更新角色失败")
|
||||
@@ -127,7 +127,7 @@ class RoleEnableResource(Resource):
|
||||
"""启用用户"""
|
||||
|
||||
def put(self, role_id):
|
||||
ret = RightsRole.query.get(role_id)
|
||||
ret = RoleModels.query.get(role_id)
|
||||
ret.enable = not ret.enable
|
||||
db.session.commit()
|
||||
|
||||
@@ -141,11 +141,11 @@ class RolePowerResource(Resource):
|
||||
|
||||
def get(self, role_id):
|
||||
# 获取角色权限
|
||||
role = RightsRole.query.filter_by(id=role_id).first()
|
||||
role = RoleModels.query.filter_by(id=role_id).first()
|
||||
# 获取权限列表的 id
|
||||
check_powers_list = [rp.id for rp in role.power]
|
||||
powers = RightsPower.query.all() # 获取所有的权限
|
||||
powers = marshal(powers, RightsPower.fields())
|
||||
powers = RightModels.query.all() # 获取所有的权限
|
||||
powers = marshal(powers, RightModels.fields())
|
||||
for i in powers:
|
||||
if int(i.get("powerId")) in check_powers_list:
|
||||
i["checkArr"] = "1"
|
||||
@@ -166,14 +166,14 @@ class RolePowerResource(Resource):
|
||||
power_list = res.power_ids.split(',')
|
||||
|
||||
""" 更新角色权限 """
|
||||
role = RightsRole.query.filter_by(id=role_id).first()
|
||||
role = RoleModels.query.filter_by(id=role_id).first()
|
||||
power_id_list = []
|
||||
for p in role.power:
|
||||
power_id_list.append(p.id)
|
||||
powers = RightsPower.query.filter(RightsPower.id.in_(power_id_list)).all()
|
||||
powers = RightModels.query.filter(RightModels.id.in_(power_id_list)).all()
|
||||
for p in powers:
|
||||
role.power.remove(p)
|
||||
powers = RightsPower.query.filter(RightsPower.id.in_(power_list)).all()
|
||||
powers = RightModels.query.filter(RightModels.id.in_(power_list)).all()
|
||||
for p in powers:
|
||||
role.power.append(p)
|
||||
db.session.commit()
|
||||
|
||||
@@ -4,10 +4,10 @@ from flask import request, jsonify, current_app
|
||||
from flask_restful import Resource
|
||||
from sqlalchemy import desc
|
||||
|
||||
from applications.common.utils.http import fail_api, success_api, table_api
|
||||
from applications.common.utils.upload import upload_one, delete_photo_by_id
|
||||
from applications.extensions import db
|
||||
from applications.models import FilePhoto
|
||||
from common.utils.http import fail_api, success_api, table_api
|
||||
from common.utils.upload import upload_one, delete_photo_by_id
|
||||
from extensions import db
|
||||
from models import PhotoModels
|
||||
|
||||
|
||||
class FilePhotosResource(Resource):
|
||||
@@ -15,11 +15,10 @@ class FilePhotosResource(Resource):
|
||||
def get(self):
|
||||
page = request.args.get('page', type=int)
|
||||
limit = request.args.get('limit', type=int)
|
||||
photo_paginate = FilePhoto.query.order_by(desc(FilePhoto.create_at)
|
||||
).paginate(page=page,
|
||||
photo_paginate = PhotoModels.query.order_by(desc(PhotoModels.create_at)
|
||||
).paginate(page=page,
|
||||
per_page=limit,
|
||||
error_out=False)
|
||||
# data = marshal(photo_paginate.items, FilePhoto.fields())
|
||||
data = [
|
||||
{
|
||||
'id': item.id,
|
||||
@@ -55,11 +54,11 @@ class FilePhotosResource(Resource):
|
||||
"""图片批量删除"""
|
||||
# TODO bugs 图片删除失败
|
||||
ids = request.form.getlist('ids[]')
|
||||
photo_name = FilePhoto.query.filter(FilePhoto.id.in_(ids)).all()
|
||||
photo_name = PhotoModels.query.filter(PhotoModels.id.in_(ids)).all()
|
||||
upload_url = current_app.config.get("UPLOADED_PHOTOS_DEST")
|
||||
for p in photo_name:
|
||||
os.remove(upload_url + '/' + p.name)
|
||||
photo = FilePhoto.query.filter(FilePhoto.id.in_(ids)).delete(synchronize_session=False)
|
||||
photo = PhotoModels.query.filter(PhotoModels.id.in_(ids)).delete(synchronize_session=False)
|
||||
db.session.commit()
|
||||
if photo:
|
||||
return success_api(message="删除成功")
|
||||
|
||||
@@ -3,10 +3,10 @@ from flask import session, redirect, url_for
|
||||
from flask_login import current_user, login_user
|
||||
from flask_restful import Resource, reqparse
|
||||
|
||||
from applications.common.gen_captcha import add_auth_session
|
||||
from applications.common.utils.http import fail_api, success_api
|
||||
from applications.common.utils.rights import record_logging
|
||||
from applications.models import CompanyUser
|
||||
from common.gen_captcha import add_auth_session
|
||||
from common.utils.http import fail_api, success_api
|
||||
from common.utils.rights import record_logging
|
||||
from models import UserModels
|
||||
|
||||
|
||||
class LoginResource(Resource):
|
||||
@@ -28,7 +28,7 @@ class LoginResource(Resource):
|
||||
|
||||
if req.captcha != s_code:
|
||||
return fail_api(message="验证码错误")
|
||||
user = CompanyUser.query.filter_by(username=req.username).first()
|
||||
user = UserModels.query.filter_by(username=req.username).first()
|
||||
|
||||
if user is None:
|
||||
return fail_api(message="不存在的用户")
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
# 个人中心
|
||||
from flask import request, jsonify
|
||||
from flask_login import login_required
|
||||
from flask_restful import Resource, reqparse
|
||||
|
||||
from applications.common.utils.http import fail_api, success_api
|
||||
from applications.extensions import db
|
||||
from applications.models import CompanyUser
|
||||
from common.utils.http import fail_api, success_api
|
||||
from extensions import db
|
||||
from models import UserModels
|
||||
|
||||
|
||||
class UserStatusResource(Resource):
|
||||
@@ -19,11 +18,11 @@ class UserStatusResource(Resource):
|
||||
res = parser.parse_args()
|
||||
|
||||
if res.operate == 1:
|
||||
user = CompanyUser.query.get(user_id)
|
||||
user = UserModels.query.get(user_id)
|
||||
user.enable = res.operate
|
||||
message = success_api(message="启动成功")
|
||||
else:
|
||||
user = CompanyUser.query.filter_by(id=res.user_id).update({"enable": res.operate})
|
||||
user = UserModels.query.filter_by(id=res.user_id).update({"enable": res.operate})
|
||||
message = success_api(message="禁用成功")
|
||||
if user:
|
||||
db.session.commit()
|
||||
@@ -37,7 +36,7 @@ class UserAvatarResource(Resource):
|
||||
|
||||
def put(self, user_id):
|
||||
url = request.json.get("avatar").get("src")
|
||||
ret = CompanyUser.query.get(user_id)
|
||||
ret = UserModels.query.get(user_id)
|
||||
ret.avatar = url
|
||||
db.session.commit()
|
||||
if not ret:
|
||||
@@ -56,7 +55,7 @@ class UserInfoResource(Resource):
|
||||
|
||||
res = parser.parse_args()
|
||||
|
||||
ret = CompanyUser.query.get(user_id)
|
||||
ret = UserModels.query.get(user_id)
|
||||
ret.username = res.username
|
||||
ret.realname = res.real_name
|
||||
ret.remark = res.details
|
||||
@@ -81,7 +80,7 @@ class UserPasswordResource(Resource):
|
||||
return fail_api(message='确认密码不一致')
|
||||
|
||||
""" 修改当前用户密码 """
|
||||
user = CompanyUser.query.get(user_id)
|
||||
user = UserModels.query.get(user_id)
|
||||
is_right = user.validate_password(res.oldPassword)
|
||||
if not is_right:
|
||||
return jsonify(success=False, message="旧密码错误")
|
||||
|
||||
@@ -3,35 +3,35 @@ from flask_login import current_user
|
||||
from flask_restful import Resource, reqparse
|
||||
from sqlalchemy import desc
|
||||
|
||||
from applications.common.utils.http import fail_api, success_api, table_api
|
||||
from applications.extensions import db
|
||||
from applications.models import CompanyUser, RightsRole, CompanyDepartment
|
||||
from applications.models import LoggingModel
|
||||
from common.utils.http import fail_api, success_api, table_api
|
||||
from extensions import db
|
||||
from models import UserModels, RoleModels, DepartmentModels
|
||||
from models import LogModel
|
||||
|
||||
|
||||
def get_current_user_logs():
|
||||
""" 获取当前用户日志 """
|
||||
log = LoggingModel.query.filter_by(url='/passport/login').filter_by(uid=current_user.id).order_by(
|
||||
desc(LoggingModel.create_at)).limit(10)
|
||||
log = LogModel.query.filter_by(url='/passport/login').filter_by(uid=current_user.id).order_by(
|
||||
desc(LogModel.create_at)).limit(10)
|
||||
return log
|
||||
|
||||
|
||||
def is_user_exists(username):
|
||||
""" 判断用户是否存在 """
|
||||
res = CompanyUser.query.filter_by(username=username).count()
|
||||
res = UserModels.query.filter_by(username=username).count()
|
||||
return bool(res)
|
||||
|
||||
|
||||
def delete_by_id(_id):
|
||||
""" 删除用户 """
|
||||
user = CompanyUser.query.filter_by(id=_id).first()
|
||||
user = UserModels.query.filter_by(id=_id).first()
|
||||
roles_id = []
|
||||
for role in user.role:
|
||||
roles_id.append(role.id)
|
||||
roles = RightsRole.query.filter(RightsRole.id.in_(roles_id)).all()
|
||||
roles = RoleModels.query.filter(RoleModels.id.in_(roles_id)).all()
|
||||
for r in roles:
|
||||
user.role.remove(r)
|
||||
res = CompanyUser.query.filter_by(id=_id).delete()
|
||||
res = UserModels.query.filter_by(id=_id).delete()
|
||||
db.session.commit()
|
||||
return res
|
||||
|
||||
@@ -43,14 +43,14 @@ def batch_remove(ids):
|
||||
|
||||
|
||||
def update_user_role(_id, roles_list):
|
||||
user = CompanyUser.query.filter_by(id=_id).first()
|
||||
user = UserModels.query.filter_by(id=_id).first()
|
||||
roles_id = []
|
||||
for role in user.role:
|
||||
roles_id.append(role.id)
|
||||
roles = RightsRole.query.filter(RightsRole.id.in_(roles_id)).all()
|
||||
roles = RoleModels.query.filter(RoleModels.id.in_(roles_id)).all()
|
||||
for r in roles:
|
||||
user.role.remove(r)
|
||||
roles = RightsRole.query.filter(RightsRole.id.in_(roles_list)).all()
|
||||
roles = RoleModels.query.filter(RoleModels.id.in_(roles_list)).all()
|
||||
for r in roles:
|
||||
user.role.append(r)
|
||||
db.session.commit()
|
||||
@@ -72,17 +72,17 @@ class UserUsersResource(Resource):
|
||||
filters = []
|
||||
|
||||
if res.real_name:
|
||||
filters.append(CompanyUser.realname.like('%' + res.real_name + '%'))
|
||||
filters.append(UserModels.realname.like('%' + res.real_name + '%'))
|
||||
if res.username:
|
||||
filters.append(CompanyUser.username.like('%' + res.username + '%'))
|
||||
filters.append(UserModels.username.like('%' + res.username + '%'))
|
||||
if res.dept_id:
|
||||
filters.append(CompanyUser.dept_id == res.dept_id)
|
||||
filters.append(UserModels.dept_id == res.dept_id)
|
||||
|
||||
paginate = CompanyUser.query.filter(*filters).paginate(page=res.page,
|
||||
per_page=res.limit,
|
||||
error_out=False)
|
||||
paginate = UserModels.query.filter(*filters).paginate(page=res.page,
|
||||
per_page=res.limit,
|
||||
error_out=False)
|
||||
|
||||
dept_name = lambda dept_id: CompanyDepartment.query.filter_by(id=dept_id).first().dept_name if dept_id else ""
|
||||
dept_name = lambda dept_id: DepartmentModels.query.filter_by(id=dept_id).first().dept_name if dept_id else ""
|
||||
user_data = [{
|
||||
'id': item.id,
|
||||
'username': item.username,
|
||||
@@ -111,7 +111,7 @@ class UserUsersResource(Resource):
|
||||
if is_user_exists(res.username):
|
||||
return fail_api(message="用户已经存在")
|
||||
|
||||
user = CompanyUser()
|
||||
user = UserModels()
|
||||
user.username = res.username
|
||||
user.realname = res.real_name
|
||||
user.set_password(res.password)
|
||||
@@ -119,8 +119,8 @@ class UserUsersResource(Resource):
|
||||
db.session.commit()
|
||||
|
||||
""" 增加用户角色 """
|
||||
user = CompanyUser.query.filter_by(id=user.id).first()
|
||||
roles = RightsRole.query.filter(RightsRole.id.in_(role_ids)).all()
|
||||
user = UserModels.query.filter_by(id=user.id).first()
|
||||
roles = RoleModels.query.filter(RoleModels.id.in_(role_ids)).all()
|
||||
for r in roles:
|
||||
user.role.append(r)
|
||||
db.session.commit()
|
||||
@@ -152,7 +152,7 @@ class UserUserResource(Resource):
|
||||
if is_user_exists(res.username):
|
||||
return fail_api(message="用户已经存在")
|
||||
|
||||
user = CompanyUser()
|
||||
user = UserModels()
|
||||
user.username = res.username
|
||||
user.realname = res.real_name
|
||||
user.set_password(res.password)
|
||||
@@ -160,8 +160,8 @@ class UserUserResource(Resource):
|
||||
db.session.commit()
|
||||
|
||||
""" 增加用户角色 """
|
||||
user = CompanyUser.query.filter_by(id=user.id).first()
|
||||
roles = RightsRole.query.filter(RightsRole.id.in_(role_ids)).all()
|
||||
user = UserModels.query.filter_by(id=user.id).first()
|
||||
roles = RoleModels.query.filter(RoleModels.id.in_(role_ids)).all()
|
||||
for r in roles:
|
||||
user.role.append(r)
|
||||
db.session.commit()
|
||||
@@ -189,7 +189,7 @@ class UserRoleResource(Resource):
|
||||
role_ids = res.role_ids.split(',')
|
||||
|
||||
# 更新用户数据
|
||||
CompanyUser.query.filter_by(id=user_id).update({'username': res.username,
|
||||
UserModels.query.filter_by(id=user_id).update({'username': res.username,
|
||||
'realname': res.real_name,
|
||||
'dept_id': res.dept_id})
|
||||
db.session.commit()
|
||||
|
||||
@@ -1,504 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
为了解决 flask_uploads 与 Werkzeug 2.0.1 冲突而直接复制源码进行适配
|
||||
原始地址: https://github.com/maxcountryman/flask-uploads/blob/master/flask_uploads.py
|
||||
"""
|
||||
|
||||
import sys
|
||||
|
||||
PY3 = sys.version_info[0] == 3
|
||||
|
||||
if PY3:
|
||||
string_types = str,
|
||||
else:
|
||||
string_types = basestring,
|
||||
|
||||
import os.path
|
||||
import posixpath
|
||||
|
||||
from flask import current_app, send_from_directory, abort, url_for
|
||||
from itertools import chain
|
||||
from werkzeug.datastructures import FileStorage
|
||||
from werkzeug.utils import secure_filename
|
||||
|
||||
from flask import Blueprint
|
||||
|
||||
# Extension presets
|
||||
|
||||
#: This just contains plain text files (.txt).
|
||||
TEXT = ('txt',)
|
||||
|
||||
#: This contains various office document formats (.rtf, .odf, .ods, .gnumeric,
|
||||
#: .abw, .doc, .docx, .xls, and .xlsx). Note that the macro-enabled versions
|
||||
#: of Microsoft Office 2007 files are not included.
|
||||
DOCUMENTS = tuple('rtf odf ods gnumeric abw doc docx xls xlsx'.split())
|
||||
|
||||
#: This contains basic image types that are viewable from most browsers (.jpg,
|
||||
#: .jpe, .jpeg, .png, .gif, .svg, and .bmp).
|
||||
IMAGES = tuple('jpg jpe jpeg png gif svg bmp'.split())
|
||||
|
||||
#: This contains audio file types (.wav, .mp3, .aac, .ogg, .oga, and .flac).
|
||||
AUDIO = tuple('wav mp3 aac ogg oga flac'.split())
|
||||
|
||||
#: This is for structured data files (.csv, .ini, .json, .plist, .xml, .yaml,
|
||||
#: and .yml).
|
||||
DATA = tuple('csv ini json plist xml yaml yml'.split())
|
||||
|
||||
#: This contains various types of scripts (.js, .php, .pl, .py .rb, and .sh).
|
||||
#: If your Web server has PHP installed and set to auto-run, you might want to
|
||||
#: add ``php`` to the DENY setting.
|
||||
SCRIPTS = tuple('js php pl py rb sh'.split())
|
||||
|
||||
#: This contains archive and compression formats (.gz, .bz2, .zip, .tar,
|
||||
#: .tgz, .txz, and .7z).
|
||||
ARCHIVES = tuple('gz bz2 zip tar tgz txz 7z'.split())
|
||||
|
||||
#: This contains shared libraries and executable files (.so, .exe and .dll).
|
||||
#: Most of the time, you will not want to allow this - it's better suited for
|
||||
#: use with `AllExcept`.
|
||||
EXECUTABLES = tuple('so exe dll'.split())
|
||||
|
||||
#: The default allowed extensions - `TEXT`, `DOCUMENTS`, `DATA`, and `IMAGES`.
|
||||
DEFAULTS = TEXT + DOCUMENTS + IMAGES + DATA
|
||||
|
||||
|
||||
class UploadNotAllowed(Exception):
|
||||
"""
|
||||
This exception is raised if the upload was not allowed. You should catch
|
||||
it in your view code and display an appropriate message to the user.
|
||||
"""
|
||||
|
||||
|
||||
def tuple_from(*iters):
|
||||
return tuple(itertools.chain(*iters))
|
||||
|
||||
|
||||
def extension(filename):
|
||||
ext = os.path.splitext(filename)[1]
|
||||
if ext.startswith('.'):
|
||||
# os.path.splitext retains . separator
|
||||
ext = ext[1:]
|
||||
return ext
|
||||
|
||||
|
||||
def lowercase_ext(filename):
|
||||
"""
|
||||
This is a helper used by UploadSet.save to provide lowercase extensions for
|
||||
all processed files, to compare with configured extensions in the same
|
||||
case.
|
||||
|
||||
.. versionchanged:: 0.1.4
|
||||
Filenames without extensions are no longer lowercased, only the
|
||||
extension is returned in lowercase, if an extension exists.
|
||||
|
||||
:param filename: The filename to ensure has a lowercase extension.
|
||||
"""
|
||||
if '.' in filename:
|
||||
main, ext = os.path.splitext(filename)
|
||||
return main + ext.lower()
|
||||
# For consistency with os.path.splitext,
|
||||
# do not treat a filename without an extension as an extension.
|
||||
# That is, do not return filename.lower().
|
||||
return filename
|
||||
|
||||
|
||||
def addslash(url):
|
||||
if url.endswith('/'):
|
||||
return url
|
||||
return url + '/'
|
||||
|
||||
|
||||
def patch_request_class(app, size=64 * 1024 * 1024):
|
||||
"""
|
||||
By default, Flask will accept uploads to an arbitrary size. While Werkzeug
|
||||
switches uploads from memory to a temporary file when they hit 500 KiB,
|
||||
it's still possible for someone to overload your disk space with a
|
||||
gigantic file.
|
||||
|
||||
This patches the app's request class's
|
||||
`~werkzeug.BaseRequest.max_content_length` attribute so that any upload
|
||||
larger than the given size is rejected with an HTTP error.
|
||||
|
||||
.. note::
|
||||
|
||||
In Flask 0.6, you can do this by setting the `MAX_CONTENT_LENGTH`
|
||||
setting, without patching the request class. To emulate this behavior,
|
||||
you can pass `None` as the size (you must pass it explicitly). That is
|
||||
the best way to call this function, as it won't break the Flask 0.6
|
||||
functionality if it exists.
|
||||
|
||||
.. versionchanged:: 0.1.1
|
||||
|
||||
:param app: The app to patch the request class of.
|
||||
:param size: The maximum size to accept, in bytes. The default is 64 MiB.
|
||||
If it is `None`, the app's `MAX_CONTENT_LENGTH` configuration
|
||||
setting will be used to patch.
|
||||
"""
|
||||
if size is None:
|
||||
if isinstance(app.request_class.__dict__['max_content_length'],
|
||||
property):
|
||||
return
|
||||
size = app.config.get('MAX_CONTENT_LENGTH')
|
||||
reqclass = app.request_class
|
||||
patched = type(reqclass.__name__, (reqclass,),
|
||||
{'max_content_length': size})
|
||||
app.request_class = patched
|
||||
|
||||
|
||||
def config_for_set(uset, app, defaults=None):
|
||||
"""
|
||||
This is a helper function for `configure_uploads` that extracts the
|
||||
configuration for a single set.
|
||||
|
||||
:param uset: The upload set.
|
||||
:param app: The app to load the configuration from.
|
||||
:param defaults: A dict with keys `url` and `dest` from the
|
||||
`UPLOADS_DEFAULT_DEST` and `DEFAULT_UPLOADS_URL`
|
||||
settings.
|
||||
"""
|
||||
config = app.config
|
||||
prefix = 'UPLOADED_%s_' % uset.name.upper()
|
||||
using_defaults = False
|
||||
if defaults is None:
|
||||
defaults = dict(dest=None, url=None)
|
||||
|
||||
allow_extns = tuple(config.get(prefix + 'ALLOW', ()))
|
||||
deny_extns = tuple(config.get(prefix + 'DENY', ()))
|
||||
destination = config.get(prefix + 'DEST')
|
||||
base_url = config.get(prefix + 'URL')
|
||||
|
||||
if destination is None:
|
||||
# the upload set's destination wasn't given
|
||||
if uset.default_dest:
|
||||
# use the "default_dest" callable
|
||||
destination = uset.default_dest(app)
|
||||
if destination is None: # still
|
||||
# use the default dest from the config
|
||||
if defaults['dest'] is not None:
|
||||
using_defaults = True
|
||||
destination = os.path.join(defaults['dest'], uset.name)
|
||||
else:
|
||||
raise RuntimeError("no destination for set %s" % uset.name)
|
||||
|
||||
if base_url is None and using_defaults and defaults['url']:
|
||||
base_url = addslash(defaults['url']) + uset.name + '/'
|
||||
|
||||
return UploadConfiguration(destination, base_url, allow_extns, deny_extns)
|
||||
|
||||
|
||||
def configure_uploads(app, upload_sets):
|
||||
"""
|
||||
Call this after the app has been configured. It will go through all the
|
||||
upload sets, get their configuration, and store the configuration on the
|
||||
app. It will also register the uploads module if it hasn't been set. This
|
||||
can be called multiple times with different upload sets.
|
||||
|
||||
.. versionchanged:: 0.1.3
|
||||
The uploads module/blueprint will only be registered if it is needed
|
||||
to serve the upload sets.
|
||||
|
||||
:param app: The `~flask.Flask` instance to get the configuration from.
|
||||
:param upload_sets: The `UploadSet` instances to configure.
|
||||
"""
|
||||
if isinstance(upload_sets, UploadSet):
|
||||
upload_sets = (upload_sets,)
|
||||
|
||||
if not hasattr(app, 'upload_set_config'):
|
||||
app.upload_set_config = {}
|
||||
set_config = app.upload_set_config
|
||||
defaults = dict(dest=app.config.get('UPLOADS_DEFAULT_DEST'),
|
||||
url=app.config.get('UPLOADS_DEFAULT_URL'))
|
||||
|
||||
for uset in upload_sets:
|
||||
config = config_for_set(uset, app, defaults)
|
||||
set_config[uset.name] = config
|
||||
|
||||
should_serve = any(s.base_url is None for s in set_config.values())
|
||||
if '_uploads' not in app.blueprints and should_serve:
|
||||
app.register_blueprint(uploads_mod)
|
||||
|
||||
|
||||
class All(object):
|
||||
"""
|
||||
This type can be used to allow all extensions. There is a predefined
|
||||
instance named `ALL`.
|
||||
"""
|
||||
|
||||
def __contains__(self, item):
|
||||
return True
|
||||
|
||||
|
||||
#: This "contains" all items. You can use it to allow all extensions to be
|
||||
#: uploaded.
|
||||
ALL = All()
|
||||
|
||||
|
||||
class AllExcept(object):
|
||||
"""
|
||||
This can be used to allow all file types except certain ones. For example,
|
||||
to ban .exe and .iso files, pass::
|
||||
|
||||
AllExcept(('exe', 'iso'))
|
||||
|
||||
to the `UploadSet` constructor as `extensions`. You can use any container,
|
||||
for example::
|
||||
|
||||
AllExcept(SCRIPTS + EXECUTABLES)
|
||||
"""
|
||||
|
||||
def __init__(self, items):
|
||||
self.items = items
|
||||
|
||||
def __contains__(self, item):
|
||||
return item not in self.items
|
||||
|
||||
|
||||
class UploadConfiguration(object):
|
||||
"""
|
||||
This holds the configuration for a single `UploadSet`. The constructor's
|
||||
arguments are also the attributes.
|
||||
|
||||
:param destination: The directory to save files to.
|
||||
:param base_url: The URL (ending with a /) that files can be downloaded
|
||||
from. If this is `None`, Flask-Uploads will serve the
|
||||
files itself.
|
||||
:param allow: A list of extensions to allow, even if they're not in the
|
||||
`UploadSet` extensions list.
|
||||
:param deny: A list of extensions to deny, even if they are in the
|
||||
`UploadSet` extensions list.
|
||||
"""
|
||||
|
||||
def __init__(self, destination, base_url=None, allow=(), deny=()):
|
||||
self.destination = destination
|
||||
self.base_url = base_url
|
||||
self.allow = allow
|
||||
self.deny = deny
|
||||
|
||||
@property
|
||||
def tuple(self):
|
||||
return (self.destination, self.base_url, self.allow, self.deny)
|
||||
|
||||
def __eq__(self, other):
|
||||
return self.tuple == other.tuple
|
||||
|
||||
|
||||
class UploadSet(object):
|
||||
"""
|
||||
This represents a single set of uploaded files. Each upload set is
|
||||
independent of the others. This can be reused across multiple application
|
||||
instances, as all configuration is stored on the application object itself
|
||||
and found with `flask.current_app`.
|
||||
|
||||
:param name: The name of this upload set. It defaults to ``files``, but
|
||||
you can pick any alphanumeric name you want. (For simplicity,
|
||||
it's best to use a plural noun.)
|
||||
:param extensions: The extensions to allow uploading in this set. The
|
||||
easiest way to do this is to add together the extension
|
||||
presets (for example, ``TEXT + DOCUMENTS + IMAGES``).
|
||||
It can be overridden by the configuration with the
|
||||
`UPLOADED_X_ALLOW` and `UPLOADED_X_DENY` configuration
|
||||
parameters. The default is `DEFAULTS`.
|
||||
:param default_dest: If given, this should be a callable. If you call it
|
||||
with the app, it should return the default upload
|
||||
destination path for that app.
|
||||
"""
|
||||
|
||||
def __init__(self, name='files', extensions=DEFAULTS, default_dest=None):
|
||||
if not name.isalnum():
|
||||
raise ValueError("Name must be alphanumeric (no underscores)")
|
||||
self.name = name
|
||||
self.extensions = extensions
|
||||
self._config = None
|
||||
self.default_dest = default_dest
|
||||
|
||||
@property
|
||||
def config(self):
|
||||
"""
|
||||
This gets the current configuration. By default, it looks up the
|
||||
current application and gets the configuration from there. But if you
|
||||
don't want to go to the full effort of setting an application, or it's
|
||||
otherwise outside of a request context, set the `_config` attribute to
|
||||
an `UploadConfiguration` instance, then set it back to `None` when
|
||||
you're done.
|
||||
"""
|
||||
if self._config is not None:
|
||||
return self._config
|
||||
try:
|
||||
return current_app.upload_set_config[self.name]
|
||||
except AttributeError:
|
||||
raise RuntimeError("cannot access configuration outside request")
|
||||
|
||||
def url(self, filename):
|
||||
"""
|
||||
This function gets the URL a file uploaded to this set would be
|
||||
accessed at. It doesn't check whether said file exists.
|
||||
|
||||
:param filename: The filename to return the URL for.
|
||||
"""
|
||||
base = self.config.base_url
|
||||
if base is None:
|
||||
return url_for('_uploads.uploaded_file', setname=self.name,
|
||||
filename=filename, _external=True)
|
||||
else:
|
||||
return base + filename
|
||||
|
||||
def path(self, filename, folder=None):
|
||||
"""
|
||||
This returns the absolute path of a file uploaded to this set. It
|
||||
doesn't actually check whether said file exists.
|
||||
|
||||
:param filename: The filename to return the path for.
|
||||
:param folder: The subfolder within the upload set previously used
|
||||
to save to.
|
||||
"""
|
||||
if folder is not None:
|
||||
target_folder = os.path.join(self.config.destination, folder)
|
||||
else:
|
||||
target_folder = self.config.destination
|
||||
return os.path.join(target_folder, filename)
|
||||
|
||||
def file_allowed(self, storage, basename):
|
||||
"""
|
||||
This tells whether a file is allowed. It should return `True` if the
|
||||
given `werkzeug.FileStorage` object can be saved with the given
|
||||
basename, and `False` if it can't. The default implementation just
|
||||
checks the extension, so you can override this if you want.
|
||||
|
||||
:param storage: The `werkzeug.FileStorage` to check.
|
||||
:param basename: The basename it will be saved under.
|
||||
"""
|
||||
return self.extension_allowed(extension(basename))
|
||||
|
||||
def extension_allowed(self, ext):
|
||||
"""
|
||||
This determines whether a specific extension is allowed. It is called
|
||||
by `file_allowed`, so if you override that but still want to check
|
||||
extensions, call back into this.
|
||||
|
||||
:param ext: The extension to check, without the dot.
|
||||
"""
|
||||
return ((ext in self.config.allow) or
|
||||
(ext in self.extensions and ext not in self.config.deny))
|
||||
|
||||
def get_basename(self, filename):
|
||||
return lowercase_ext(secure_filename(filename))
|
||||
|
||||
def save(self, storage, folder=None, name=None):
|
||||
"""
|
||||
This saves a `werkzeug.FileStorage` into this upload set. If the
|
||||
upload is not allowed, an `UploadNotAllowed` error will be raised.
|
||||
Otherwise, the file will be saved and its name (including the folder)
|
||||
will be returned.
|
||||
|
||||
:param storage: The uploaded file to save.
|
||||
:param folder: The subfolder within the upload set to save to.
|
||||
:param name: The name to save the file as. If it ends with a dot, the
|
||||
file's extension will be appended to the end. (If you
|
||||
are using `name`, you can include the folder in the
|
||||
`name` instead of explicitly using `folder`, i.e.
|
||||
``uset.save(file, name="someguy/photo_123.")``
|
||||
"""
|
||||
if not isinstance(storage, FileStorage):
|
||||
raise TypeError("storage must be a werkzeug.FileStorage")
|
||||
|
||||
if folder is None and name is not None and "/" in name:
|
||||
folder, name = os.path.split(name)
|
||||
|
||||
basename = self.get_basename(storage.filename)
|
||||
if name:
|
||||
if name.endswith('.'):
|
||||
basename = name + extension(basename)
|
||||
else:
|
||||
basename = name
|
||||
|
||||
if not self.file_allowed(storage, basename):
|
||||
raise UploadNotAllowed()
|
||||
|
||||
if folder:
|
||||
target_folder = os.path.join(self.config.destination, folder)
|
||||
else:
|
||||
target_folder = self.config.destination
|
||||
if not os.path.exists(target_folder):
|
||||
os.makedirs(target_folder)
|
||||
if os.path.exists(os.path.join(target_folder, basename)):
|
||||
basename = self.resolve_conflict(target_folder, basename)
|
||||
|
||||
target = os.path.join(target_folder, basename)
|
||||
storage.save(target)
|
||||
if folder:
|
||||
return posixpath.join(folder, basename)
|
||||
else:
|
||||
return basename
|
||||
|
||||
def resolve_conflict(self, target_folder, basename):
|
||||
"""
|
||||
If a file with the selected name already exists in the target folder,
|
||||
this method is called to resolve the conflict. It should return a new
|
||||
basename for the file.
|
||||
|
||||
The default implementation splits the name and extension and adds a
|
||||
suffix to the name consisting of an underscore and a number, and tries
|
||||
that until it finds one that doesn't exist.
|
||||
|
||||
:param target_folder: The absolute path to the target.
|
||||
:param basename: The file's original basename.
|
||||
"""
|
||||
name, ext = os.path.splitext(basename)
|
||||
count = 0
|
||||
while True:
|
||||
count = count + 1
|
||||
newname = '%s_%d%s' % (name, count, ext)
|
||||
if not os.path.exists(os.path.join(target_folder, newname)):
|
||||
return newname
|
||||
|
||||
|
||||
uploads_mod = Blueprint('_uploads', __name__, url_prefix='/_uploads')
|
||||
|
||||
|
||||
@uploads_mod.route('/<setname>/<path:filename>')
|
||||
def uploaded_file(setname, filename):
|
||||
config = current_app.upload_set_config.get(setname)
|
||||
if config is None:
|
||||
abort(404)
|
||||
return send_from_directory(config.destination, filename)
|
||||
|
||||
|
||||
class TestingFileStorage(FileStorage):
|
||||
"""
|
||||
This is a helper for testing upload behavior in your application. You
|
||||
can manually create it, and its save method is overloaded to set `saved`
|
||||
to the name of the file it was saved to. All of these parameters are
|
||||
optional, so only bother setting the ones relevant to your application.
|
||||
|
||||
:param stream: A stream. The default is an empty stream.
|
||||
:param filename: The filename uploaded from the client. The default is the
|
||||
stream's name.
|
||||
:param name: The name of the form field it was loaded from. The default is
|
||||
`None`.
|
||||
:param content_type: The content type it was uploaded as. The default is
|
||||
``application/octet-stream``.
|
||||
:param content_length: How long it is. The default is -1.
|
||||
:param headers: Multipart headers as a `werkzeug.Headers`. The default is
|
||||
`None`.
|
||||
"""
|
||||
|
||||
def __init__(self, stream=None, filename=None, name=None,
|
||||
content_type='application/octet-stream', content_length=-1,
|
||||
headers=None):
|
||||
FileStorage.__init__(self, stream, filename, name=name,
|
||||
content_type=content_type, content_length=content_length,
|
||||
headers=None)
|
||||
self.saved = None
|
||||
|
||||
def save(self, dst, buffer_size=16384):
|
||||
"""
|
||||
This marks the file as saved by setting the `saved` attribute to the
|
||||
name of the file it was saved to.
|
||||
|
||||
:param dst: The file to save to.
|
||||
:param buffer_size: Ignored.
|
||||
"""
|
||||
if isinstance(dst, string_types):
|
||||
self.saved = dst
|
||||
else:
|
||||
self.saved = dst.name
|
||||
@@ -1,43 +0,0 @@
|
||||
from captcha.image import ImageCaptcha
|
||||
from io import BytesIO
|
||||
from PIL import Image
|
||||
from random import choices
|
||||
|
||||
from flask import session, make_response
|
||||
from flask_login import current_user
|
||||
|
||||
|
||||
def gen_captcha(content='0123456789'):
|
||||
""" 生成验证码 """
|
||||
image = ImageCaptcha()
|
||||
# 获取字符串
|
||||
captcha_text = "".join(choices(content, k=4))
|
||||
# 生成图像
|
||||
captcha_image = Image.open(image.generate(captcha_text))
|
||||
return captcha_text, captcha_image
|
||||
|
||||
|
||||
# 生成验证码
|
||||
def get_captcha_image():
|
||||
code, image = gen_captcha()
|
||||
out = BytesIO()
|
||||
session["code"] = code
|
||||
image.save(out, 'png')
|
||||
out.seek(0)
|
||||
resp = make_response(out.read())
|
||||
resp.content_type = 'image/png'
|
||||
return resp, code
|
||||
|
||||
|
||||
# 授权路由存入session
|
||||
def add_auth_session():
|
||||
role = current_user.role
|
||||
user_power = []
|
||||
for i in role:
|
||||
if i.enable == 0:
|
||||
continue
|
||||
for p in i.power:
|
||||
if p.enable == 0:
|
||||
continue
|
||||
user_power.append(p.code)
|
||||
session['permissions'] = user_power
|
||||
@@ -1,36 +0,0 @@
|
||||
import typing as t
|
||||
|
||||
|
||||
def success_api(message: str = "成功", code: int = 200) -> t.Dict:
|
||||
""" 成功响应 默认值”成功“ """
|
||||
return dict(success=True, message=message, code=code)
|
||||
|
||||
|
||||
def fail_api(message: str = "失败", code: int = 404) -> t.Dict:
|
||||
""" 失败响应 默认值“失败” """
|
||||
return dict(success=False, message=message, code=code)
|
||||
|
||||
|
||||
def table_api(success: bool = True,
|
||||
message: str = "",
|
||||
result: t.Union[dict, list] = None,
|
||||
code: int = 0) -> t.Dict:
|
||||
"""
|
||||
动态表格渲染响应
|
||||
此方法返回数据给前端
|
||||
{
|
||||
'success': True,
|
||||
'code': 10002,
|
||||
'message': '提示消息',
|
||||
'result':{'items':[],'total': 100}
|
||||
}
|
||||
|
||||
注:lay_ui 表格数据需要指定 code=0
|
||||
"""
|
||||
ret = {
|
||||
'success': success,
|
||||
'message': message,
|
||||
'code': code,
|
||||
'result': result,
|
||||
}
|
||||
return ret
|
||||
@@ -1,61 +0,0 @@
|
||||
import typing as t
|
||||
from functools import wraps
|
||||
|
||||
from flask import abort, request, jsonify, session
|
||||
from flask_login import login_required
|
||||
from flask_login import current_user
|
||||
|
||||
from applications.extensions import db
|
||||
from applications.models import LoggingModel
|
||||
|
||||
|
||||
def record_logging(success: bool = True) -> None:
|
||||
"""
|
||||
记录用户日志数据
|
||||
"""
|
||||
info = {
|
||||
'method': request.method,
|
||||
'url': request.path,
|
||||
'ip': request.remote_addr,
|
||||
'user_agent': request.headers.get('User-Agent'),
|
||||
'desc': str(dict(request.values)),
|
||||
'uid': current_user.id,
|
||||
'success': success
|
||||
}
|
||||
log = LoggingModel()
|
||||
for key, value in info.items():
|
||||
setattr(log, key, value)
|
||||
|
||||
db.session.add(log)
|
||||
db.session.commit()
|
||||
|
||||
|
||||
def view_logging_required(func: t.Callable) -> t.Callable:
|
||||
"""
|
||||
日志装饰器,用于记录请求
|
||||
"""
|
||||
|
||||
@wraps(func)
|
||||
def wrapper(*args, **kwargs) -> t.Callable:
|
||||
record_logging()
|
||||
return func(*args, **kwargs)
|
||||
|
||||
return wrapper
|
||||
|
||||
|
||||
def permission_required(permission: str) -> t.Callable:
|
||||
"""
|
||||
权限装饰器,用于过滤需要的权限
|
||||
"""
|
||||
|
||||
def decorator(func: t.Callable):
|
||||
@wraps(func)
|
||||
def wrapper(*args, **kwargs) -> t.Callable:
|
||||
if permission not in session.get('permissions'):
|
||||
record_logging(success=False)
|
||||
abort(403)
|
||||
return func(*args, **kwargs)
|
||||
|
||||
return wrapper
|
||||
|
||||
return decorator
|
||||
@@ -1,30 +0,0 @@
|
||||
import os
|
||||
|
||||
from flask import current_app
|
||||
|
||||
from applications.common.flask_uploads import UploadSet, IMAGES
|
||||
from applications.extensions import db
|
||||
from applications.models import FilePhoto
|
||||
|
||||
photos = UploadSet('photos', IMAGES)
|
||||
|
||||
|
||||
def upload_one(photo, mime):
|
||||
filename = photos.save(photo)
|
||||
file_url = photos.url(filename)
|
||||
|
||||
upload_url = current_app.config.get("UPLOADED_PHOTOS_DEST")
|
||||
size = os.path.getsize(upload_url + '/' + filename)
|
||||
photo = FilePhoto(name=filename, href=file_url, mime=mime, size=size)
|
||||
db.session.add(photo)
|
||||
db.session.commit()
|
||||
return file_url
|
||||
|
||||
|
||||
def delete_photo_by_id(_id):
|
||||
photo_name = FilePhoto.query.filter_by(id=_id).first().name
|
||||
photo = FilePhoto.query.filter_by(id=_id).delete()
|
||||
db.session.commit()
|
||||
upload_url = current_app.config.get("UPLOADED_PHOTOS_DEST")
|
||||
os.remove(upload_url + '/' + photo_name)
|
||||
return photo
|
||||
@@ -1 +0,0 @@
|
||||
from .config import config
|
||||
@@ -1,24 +0,0 @@
|
||||
SYSTEM_NAME = "Pear Admin"
|
||||
# 主题面板的链接列表配置
|
||||
SYSTEM_PANEL_LINKS = [
|
||||
{
|
||||
"icon": "layui-icon layui-icon-auz",
|
||||
"title": "官方网站",
|
||||
"href": "http://www.pearadmin.com"
|
||||
},
|
||||
{
|
||||
"icon": "layui-icon layui-icon-auz",
|
||||
"title": "开发文档",
|
||||
"href": "http://www.pearadmin.com"
|
||||
},
|
||||
{
|
||||
"icon": "layui-icon layui-icon-auz",
|
||||
"title": "开源地址",
|
||||
"href": "https://gitee.com/Jmysy/Pear-Admin-Layui"
|
||||
}
|
||||
]
|
||||
|
||||
UPLOADED_PHOTOS_DEST = 'static/upload'
|
||||
UPLOADED_FILES_ALLOW = ['gif', 'jpg']
|
||||
# JSON配置
|
||||
JSON_AS_ASCII = False
|
||||
@@ -1,54 +0,0 @@
|
||||
import logging
|
||||
import os
|
||||
|
||||
|
||||
class BaseConfig:
|
||||
SECRET_KEY = os.getenv('SECRET_KEY', 'dev key')
|
||||
|
||||
# redis配置
|
||||
REDIS_HOST = os.getenv('REDIS_HOST') or "127.0.0.1"
|
||||
REDIS_PORT = int(os.getenv('REDIS_PORT') or 6379)
|
||||
|
||||
# mysql 配置
|
||||
MYSQL_USERNAME = os.getenv('MYSQL_USERNAME') or "root"
|
||||
MYSQL_PASSWORD = os.getenv('MYSQL_PASSWORD') or "123456"
|
||||
MYSQL_HOST = os.getenv('MYSQL_HOST') or "127.0.0.1"
|
||||
MYSQL_PORT = int(os.getenv('MYSQL_PORT') or 3306)
|
||||
MYSQL_DATABASE = os.getenv('MYSQL_DATABASE') or "PearAdminFlask"
|
||||
|
||||
UPLOADED_PHOTOS_DEST = '/static'
|
||||
|
||||
# mysql 数据库的配置信息
|
||||
SQLALCHEMY_DATABASE_URI = f"mysql+pymysql://{MYSQL_USERNAME}:{MYSQL_PASSWORD}@{MYSQL_HOST}:{MYSQL_PORT}/{MYSQL_DATABASE}"
|
||||
# 默认日志等级
|
||||
LOG_LEVEL = logging.WARN
|
||||
|
||||
|
||||
class TestingConfig(BaseConfig):
|
||||
""" 测试配置 """
|
||||
SQLALCHEMY_DATABASE_URI = 'sqlite:///:memory:' # 内存数据库
|
||||
|
||||
|
||||
class DevelopmentConfig(BaseConfig):
|
||||
""" 开发配置 """
|
||||
SQLALCHEMY_DATABASE_URI = r'sqlite:///sql_pear_admin.db'
|
||||
SQLALCHEMY_TRACK_MODIFICATIONS = True
|
||||
SQLALCHEMY_ECHO = False
|
||||
|
||||
UPLOADED_PHOTOS_DEST = os.path.join(os.path.dirname(os.path.abspath(__name__)), 'static', 'upload')
|
||||
|
||||
|
||||
class ProductionConfig(BaseConfig):
|
||||
"""生成环境配置"""
|
||||
SQLALCHEMY_TRACK_MODIFICATIONS = False
|
||||
SQLALCHEMY_ECHO = False
|
||||
SQLALCHEMY_POOL_RECYCLE = 8
|
||||
|
||||
LOG_LEVEL = logging.ERROR
|
||||
|
||||
|
||||
config = {
|
||||
'development': DevelopmentConfig,
|
||||
'testing': TestingConfig,
|
||||
'production': ProductionConfig
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
import json
|
||||
import os
|
||||
|
||||
path = os.path.dirname(os.path.abspath(__file__))
|
||||
cp_dept_data_list = json.loads(open(os.path.join(path, 'cp_dept.json'), encoding='utf-8').read())
|
||||
cp_user_data_list = json.loads(open(os.path.join(path, 'cp_user.json'), encoding='utf-8').read())
|
||||
file_photo_data_list = json.loads(open(os.path.join(path, 'file_photo.json'), encoding='utf-8').read())
|
||||
rt_power_data_list = json.loads(open(os.path.join(path, 'rt_power.json'), encoding='utf-8').read())
|
||||
rt_role_data_list = json.loads(open(os.path.join(path, 'rt_role.json'), encoding='utf-8').read())
|
||||
rt_role_power_data_list = json.loads(open(os.path.join(path, 'rt_role_power.json'), encoding='utf-8').read())
|
||||
rt_user_role_data_list = json.loads(open(os.path.join(path, 'rt_user_role.json'), encoding='utf-8').read())
|
||||
@@ -1,72 +0,0 @@
|
||||
[
|
||||
{
|
||||
"id": 1,
|
||||
"parent_id": 0,
|
||||
"dept_name": "总公司",
|
||||
"sort": 1,
|
||||
"leader": "就眠仪式",
|
||||
"phone": "12312345679",
|
||||
"email": "123qq.com",
|
||||
"status": 1,
|
||||
"comment": null,
|
||||
"address": "这是总公司",
|
||||
"create_at": null,
|
||||
"update_at": "2021-06-01 17:23:20"
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"parent_id": 1,
|
||||
"dept_name": "济南分公司",
|
||||
"sort": 2,
|
||||
"leader": "就眠仪式",
|
||||
"phone": "12312345678",
|
||||
"email": "1234qq.com",
|
||||
"status": 1,
|
||||
"comment": null,
|
||||
"address": "这是济南",
|
||||
"create_at": "2021-06-01 17:24:33",
|
||||
"update_at": "2021-06-01 17:25:19"
|
||||
},
|
||||
{
|
||||
"id": 5,
|
||||
"parent_id": 1,
|
||||
"dept_name": "唐山分公司",
|
||||
"sort": 4,
|
||||
"leader": "mkg",
|
||||
"phone": "12312345678",
|
||||
"email": "123@qq.com",
|
||||
"status": 1,
|
||||
"comment": null,
|
||||
"address": "这是唐山",
|
||||
"create_at": "2021-06-01 17:25:15",
|
||||
"update_at": "2021-06-01 17:25:20"
|
||||
},
|
||||
{
|
||||
"id": 7,
|
||||
"parent_id": 4,
|
||||
"dept_name": "济南分公司开发部",
|
||||
"sort": 5,
|
||||
"leader": "就眠仪式",
|
||||
"phone": "12312345678",
|
||||
"email": "123@qq.com",
|
||||
"status": 1,
|
||||
"comment": null,
|
||||
"address": "测试",
|
||||
"create_at": "2021-06-01 17:27:39",
|
||||
"update_at": "2021-06-01 17:27:39"
|
||||
},
|
||||
{
|
||||
"id": 8,
|
||||
"parent_id": 5,
|
||||
"dept_name": "唐山测试部",
|
||||
"sort": 6,
|
||||
"leader": "mkg",
|
||||
"phone": "12312345678",
|
||||
"email": "123@qq.com",
|
||||
"status": 1,
|
||||
"comment": null,
|
||||
"address": "测试部",
|
||||
"create_at": "2021-06-01 17:28:27",
|
||||
"update_at": "2021-06-01 17:28:27"
|
||||
}
|
||||
]
|
||||
@@ -1,38 +0,0 @@
|
||||
[
|
||||
{
|
||||
"id": 1,
|
||||
"username": "admin",
|
||||
"password_hash": "pbkdf2:sha256:150000$raM7mDSr$58fe069c3eac01531fc8af85e6fc200655dd2588090530084d182e6ec9d52c85",
|
||||
"create_at": null,
|
||||
"update_at": "2021-06-01 17:28:55",
|
||||
"enable": 1,
|
||||
"realname": "超级管理",
|
||||
"remark": "要是不能把握时机,就要终身蹭蹬,一事无成!",
|
||||
"avatar": "http://127.0.0.1:5000/_uploads/photos/1617291580000.jpg",
|
||||
"dept_id": 1
|
||||
},
|
||||
{
|
||||
"id": 7,
|
||||
"username": "test",
|
||||
"password_hash": "pbkdf2:sha256:150000$cRS8bYNh$adb57e64d929863cf159f924f74d0634f1fecc46dba749f1bfaca03da6d2e3ac",
|
||||
"create_at": "2021-03-22 20:03:42",
|
||||
"update_at": "2021-06-01 17:29:47",
|
||||
"enable": 1,
|
||||
"realname": "超级管理",
|
||||
"remark": "要是不能把握时机,就要终身蹭蹬,一事无成",
|
||||
"avatar": "/static/admin/admin/images/avatar.jpg",
|
||||
"dept_id": 1
|
||||
},
|
||||
{
|
||||
"id": 8,
|
||||
"username": "wind",
|
||||
"password_hash": "pbkdf2:sha256:150000$skME1obT$6a2c20cd29f89d7d2f21d9e373a7e3445f70ebce3ef1c3a555e42a7d17170b37",
|
||||
"create_at": "2021-06-01 17:30:39",
|
||||
"update_at": "2021-06-01 17:30:52",
|
||||
"enable": 1,
|
||||
"realname": "风",
|
||||
"remark": null,
|
||||
"avatar": "/static/admin/admin/images/avatar.jpg",
|
||||
"dept_id": 7
|
||||
}
|
||||
]
|
||||
@@ -1,18 +0,0 @@
|
||||
[
|
||||
{
|
||||
"id": 3,
|
||||
"name": "6958819_pear-admin_1607443454_1.png",
|
||||
"href": "http://127.0.0.1:5000/_uploads/photos/6958819_pear-admin_1607443454_1.png",
|
||||
"mime": "image/png",
|
||||
"size": "2204",
|
||||
"create_time": "2021-03-19 18:53:02"
|
||||
},
|
||||
{
|
||||
"id": 17,
|
||||
"name": "1617291580000.jpg",
|
||||
"href": "http://127.0.0.1:5000/_uploads/photos/1617291580000.jpg",
|
||||
"mime": "image/png",
|
||||
"size": "94211",
|
||||
"create_time": "2021-04-01 23:39:41"
|
||||
}
|
||||
]
|
||||
@@ -1,324 +0,0 @@
|
||||
[
|
||||
{
|
||||
"id": 1,
|
||||
"name": "系统管理",
|
||||
"type": "0",
|
||||
"code": "",
|
||||
"url": null,
|
||||
"open_type": null,
|
||||
"parent_id": "0",
|
||||
"icon": "layui-icon layui-icon-set-fill",
|
||||
"sort": 1,
|
||||
"create_time": null,
|
||||
"update_time": null,
|
||||
"enable": 1
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"name": "用户管理",
|
||||
"type": "1",
|
||||
"code": "admin:user:main",
|
||||
"url": "/users/",
|
||||
"open_type": "_iframe",
|
||||
"parent_id": "1",
|
||||
"icon": "layui-icon layui-icon layui-icon layui-icon layui-icon-rate",
|
||||
"sort": 1,
|
||||
"create_time": null,
|
||||
"update_time": null,
|
||||
"enable": 1
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"name": "权限管理",
|
||||
"type": "1",
|
||||
"code": "admin:power:main",
|
||||
"url": "/rights/",
|
||||
"open_type": "_iframe",
|
||||
"parent_id": "1",
|
||||
"icon": null,
|
||||
"sort": 2,
|
||||
"create_time": null,
|
||||
"update_time": null,
|
||||
"enable": 1
|
||||
},
|
||||
{
|
||||
"id": 9,
|
||||
"name": "角色管理",
|
||||
"type": "1",
|
||||
"code": "admin:role:main",
|
||||
"url": "/admin/role",
|
||||
"open_type": "_iframe",
|
||||
"parent_id": "1",
|
||||
"icon": "layui-icon layui-icon-username",
|
||||
"sort": 2,
|
||||
"create_time": "2021-03-16 22:24:58",
|
||||
"update_time": "2021-03-25 19:15:24",
|
||||
"enable": 1
|
||||
},
|
||||
{
|
||||
"id": 13,
|
||||
"name": "日志管理",
|
||||
"type": "1",
|
||||
"code": "admin:log:main",
|
||||
"url": "/logs",
|
||||
"open_type": "_iframe",
|
||||
"parent_id": "1",
|
||||
"icon": "layui-icon layui-icon-read",
|
||||
"sort": 4,
|
||||
"create_time": "2021-03-18 22:37:10",
|
||||
"update_time": "2021-06-03 11:06:25",
|
||||
"enable": 1
|
||||
},
|
||||
{
|
||||
"id": 17,
|
||||
"name": "文件管理",
|
||||
"type": "0",
|
||||
"code": "",
|
||||
"url": "",
|
||||
"open_type": "",
|
||||
"parent_id": "0",
|
||||
"icon": "layui-icon layui-icon-camera",
|
||||
"sort": 2,
|
||||
"create_time": "2021-03-19 18:56:23",
|
||||
"update_time": "2021-03-25 19:15:08",
|
||||
"enable": 1
|
||||
},
|
||||
{
|
||||
"id": 18,
|
||||
"name": "图片上传",
|
||||
"type": "1",
|
||||
"code": "admin:file:main",
|
||||
"url": "/file",
|
||||
"open_type": "_iframe",
|
||||
"parent_id": "17",
|
||||
"icon": "layui-icon layui-icon-camera",
|
||||
"sort": 5,
|
||||
"create_time": "2021-03-19 18:57:19",
|
||||
"update_time": "2021-03-25 19:15:13",
|
||||
"enable": 1
|
||||
},
|
||||
{
|
||||
"id": 21,
|
||||
"name": "权限增加",
|
||||
"type": "2",
|
||||
"code": "admin:power:add",
|
||||
"url": "",
|
||||
"open_type": "",
|
||||
"parent_id": "4",
|
||||
"icon": "layui-icon layui-icon-add-circle",
|
||||
"sort": 1,
|
||||
"create_time": "2021-03-22 19:43:52",
|
||||
"update_time": "2021-03-25 19:15:22",
|
||||
"enable": 1
|
||||
},
|
||||
{
|
||||
"id": 22,
|
||||
"name": "用户增加",
|
||||
"type": "2",
|
||||
"code": "admin:user:add",
|
||||
"url": "",
|
||||
"open_type": "",
|
||||
"parent_id": "3",
|
||||
"icon": "layui-icon layui-icon-add-circle",
|
||||
"sort": 1,
|
||||
"create_time": "2021-03-22 19:45:40",
|
||||
"update_time": "2021-03-25 19:15:17",
|
||||
"enable": 1
|
||||
},
|
||||
{
|
||||
"id": 23,
|
||||
"name": "用户编辑",
|
||||
"type": "2",
|
||||
"code": "admin:user:edit",
|
||||
"url": "",
|
||||
"open_type": "",
|
||||
"parent_id": "3",
|
||||
"icon": "layui-icon layui-icon-rate",
|
||||
"sort": 2,
|
||||
"create_time": "2021-03-22 19:46:15",
|
||||
"update_time": "2021-03-25 19:15:18",
|
||||
"enable": 1
|
||||
},
|
||||
{
|
||||
"id": 24,
|
||||
"name": "用户删除",
|
||||
"type": "2",
|
||||
"code": "admin:user:remove",
|
||||
"url": "",
|
||||
"open_type": "",
|
||||
"parent_id": "3",
|
||||
"icon": "layui-icon None",
|
||||
"sort": 3,
|
||||
"create_time": "2021-03-22 19:46:51",
|
||||
"update_time": "2021-03-25 19:15:18",
|
||||
"enable": 1
|
||||
},
|
||||
{
|
||||
"id": 25,
|
||||
"name": "权限编辑",
|
||||
"type": "2",
|
||||
"code": "admin:power:edit",
|
||||
"url": "",
|
||||
"open_type": "",
|
||||
"parent_id": "4",
|
||||
"icon": "layui-icon layui-icon-edit",
|
||||
"sort": 2,
|
||||
"create_time": "2021-03-22 19:47:36",
|
||||
"update_time": "2021-03-25 19:15:22",
|
||||
"enable": 1
|
||||
},
|
||||
{
|
||||
"id": 26,
|
||||
"name": "用户删除",
|
||||
"type": "2",
|
||||
"code": "admin:power:remove",
|
||||
"url": "",
|
||||
"open_type": "",
|
||||
"parent_id": "4",
|
||||
"icon": "layui-icon layui-icon-delete",
|
||||
"sort": 3,
|
||||
"create_time": "2021-03-22 19:48:17",
|
||||
"update_time": "2021-03-25 19:15:23",
|
||||
"enable": 1
|
||||
},
|
||||
{
|
||||
"id": 27,
|
||||
"name": "用户增加",
|
||||
"type": "2",
|
||||
"code": "admin:role:add",
|
||||
"url": "",
|
||||
"open_type": "",
|
||||
"parent_id": "9",
|
||||
"icon": "layui-icon layui-icon-add-circle",
|
||||
"sort": 1,
|
||||
"create_time": "2021-03-22 19:49:09",
|
||||
"update_time": "2021-03-25 19:15:24",
|
||||
"enable": 1
|
||||
},
|
||||
{
|
||||
"id": 28,
|
||||
"name": "角色编辑",
|
||||
"type": "2",
|
||||
"code": "admin:role:edit",
|
||||
"url": "",
|
||||
"open_type": "",
|
||||
"parent_id": "9",
|
||||
"icon": "layui-icon layui-icon-edit",
|
||||
"sort": 2,
|
||||
"create_time": "2021-03-22 19:49:41",
|
||||
"update_time": "2021-03-25 19:15:25",
|
||||
"enable": 1
|
||||
},
|
||||
{
|
||||
"id": 29,
|
||||
"name": "角色删除",
|
||||
"type": "2",
|
||||
"code": "admin:role:remove",
|
||||
"url": "",
|
||||
"open_type": "",
|
||||
"parent_id": "9",
|
||||
"icon": "layui-icon layui-icon-delete",
|
||||
"sort": 3,
|
||||
"create_time": "2021-03-22 19:50:15",
|
||||
"update_time": "2021-03-25 19:15:26",
|
||||
"enable": 1
|
||||
},
|
||||
{
|
||||
"id": 30,
|
||||
"name": "角色授权",
|
||||
"type": "2",
|
||||
"code": "admin:role:power",
|
||||
"url": "",
|
||||
"open_type": "",
|
||||
"parent_id": "9",
|
||||
"icon": "layui-icon layui-icon-component",
|
||||
"sort": 4,
|
||||
"create_time": "2021-03-22 19:50:54",
|
||||
"update_time": "2021-03-25 19:15:26",
|
||||
"enable": 1
|
||||
},
|
||||
{
|
||||
"id": 31,
|
||||
"name": "图片增加",
|
||||
"type": "2",
|
||||
"code": "admin:file:add",
|
||||
"url": "",
|
||||
"open_type": "",
|
||||
"parent_id": "18",
|
||||
"icon": "layui-icon layui-icon-add-circle",
|
||||
"sort": 1,
|
||||
"create_time": "2021-03-22 19:58:05",
|
||||
"update_time": "2021-03-25 19:15:28",
|
||||
"enable": 1
|
||||
},
|
||||
{
|
||||
"id": 32,
|
||||
"name": "图片删除",
|
||||
"type": "2",
|
||||
"code": "admin:file:delete",
|
||||
"url": "",
|
||||
"open_type": "",
|
||||
"parent_id": "18",
|
||||
"icon": "layui-icon layui-icon-delete",
|
||||
"sort": 2,
|
||||
"create_time": "2021-03-22 19:58:45",
|
||||
"update_time": "2021-03-25 19:15:29",
|
||||
"enable": 1
|
||||
},
|
||||
{
|
||||
"id": 48,
|
||||
"name": "部门管理",
|
||||
"type": "1",
|
||||
"code": "admin:dept:main",
|
||||
"url": "/dept",
|
||||
"open_type": "_iframe",
|
||||
"parent_id": "1",
|
||||
"icon": "layui-icon layui-icon-group",
|
||||
"sort": 3,
|
||||
"create_time": "2021-06-01 16:22:11",
|
||||
"update_time": "2021-06-01 16:22:11",
|
||||
"enable": 1
|
||||
},
|
||||
{
|
||||
"id": 49,
|
||||
"name": "部门增加",
|
||||
"type": "2",
|
||||
"code": "admin:dept:add",
|
||||
"url": "",
|
||||
"open_type": "",
|
||||
"parent_id": "48",
|
||||
"icon": "layui-icon None",
|
||||
"sort": 1,
|
||||
"create_time": "2021-06-01 17:35:52",
|
||||
"update_time": "2021-06-01 17:36:15",
|
||||
"enable": 1
|
||||
},
|
||||
{
|
||||
"id": 50,
|
||||
"name": "部门编辑",
|
||||
"type": "2",
|
||||
"code": "admin:dept:edit",
|
||||
"url": "",
|
||||
"open_type": "",
|
||||
"parent_id": "48",
|
||||
"icon": "layui-icon ",
|
||||
"sort": 2,
|
||||
"create_time": "2021-06-01 17:36:41",
|
||||
"update_time": "2021-06-01 17:36:41",
|
||||
"enable": 1
|
||||
},
|
||||
{
|
||||
"id": 51,
|
||||
"name": "部门删除",
|
||||
"type": "2",
|
||||
"code": "admin:dept:remove",
|
||||
"url": "",
|
||||
"open_type": "",
|
||||
"parent_id": "48",
|
||||
"icon": "layui-icon None",
|
||||
"sort": 3,
|
||||
"create_time": "2021-06-01 17:37:15",
|
||||
"update_time": "2021-06-01 17:37:26",
|
||||
"enable": 1
|
||||
}
|
||||
]
|
||||
@@ -1,24 +0,0 @@
|
||||
[
|
||||
{
|
||||
"id": 1,
|
||||
"name": "管理员",
|
||||
"code": "admin",
|
||||
"remark": null,
|
||||
"details": "管理员",
|
||||
"sort": 1,
|
||||
"create_time": null,
|
||||
"update_time": null,
|
||||
"enable": 1
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"name": "普通用户",
|
||||
"code": "common",
|
||||
"remark": null,
|
||||
"details": "只有查看,没有增删改权限",
|
||||
"sort": 2,
|
||||
"create_time": "2021-03-22 20:02:38",
|
||||
"update_time": "2021-04-01 22:29:56",
|
||||
"enable": 1
|
||||
}
|
||||
]
|
||||
@@ -1,40 +0,0 @@
|
||||
[
|
||||
[237, 1, 1],
|
||||
[238, 3, 1],
|
||||
[239, 4, 1],
|
||||
[240, 9, 1],
|
||||
[241, 12, 1],
|
||||
[242, 13, 1],
|
||||
[243, 17, 1],
|
||||
[244, 18, 1],
|
||||
[245, 21, 1],
|
||||
[246, 22, 1],
|
||||
[247, 23, 1],
|
||||
[248, 24, 1],
|
||||
[249, 25, 1],
|
||||
[250, 26, 1],
|
||||
[251, 27, 1],
|
||||
[252, 28, 1],
|
||||
[253, 29, 1],
|
||||
[254, 30, 1],
|
||||
[255, 31, 1],
|
||||
[256, 32, 1],
|
||||
[257, 44, 1],
|
||||
[258, 45, 1],
|
||||
[259, 46, 1],
|
||||
[260, 47, 1],
|
||||
[261, 48, 1],
|
||||
[262, 49, 1],
|
||||
[263, 50, 1],
|
||||
[264, 51, 1],
|
||||
[265, 1, 2],
|
||||
[266, 3, 2],
|
||||
[267, 4, 2],
|
||||
[268, 9, 2],
|
||||
[269, 12, 2],
|
||||
[270, 13, 2],
|
||||
[271, 17, 2],
|
||||
[272, 18, 2],
|
||||
[273, 44, 2],
|
||||
[274, 48, 2]
|
||||
]
|
||||
@@ -1,5 +0,0 @@
|
||||
[
|
||||
[21, 1, 1],
|
||||
[22, 7, 2],
|
||||
[24, 8, 2]
|
||||
]
|
||||
@@ -1,17 +0,0 @@
|
||||
from flask import Flask
|
||||
|
||||
from .init_databases import register_script
|
||||
from .init_sqlalchemy import db, init_databases
|
||||
from .init_login import init_login_manager
|
||||
from .init_template_directives import init_template_directives
|
||||
from .init_error_views import init_error_views
|
||||
|
||||
|
||||
def init_plugs(app: Flask) -> None:
|
||||
init_login_manager(app)
|
||||
init_databases(app)
|
||||
init_template_directives(app)
|
||||
init_error_views(app)
|
||||
|
||||
# 生成测试数据的命令,生成环境可以注释
|
||||
register_script(app)
|
||||
@@ -1,76 +0,0 @@
|
||||
from flask import Flask
|
||||
import re
|
||||
from datetime import datetime
|
||||
|
||||
date_str = re.compile('\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d$')
|
||||
|
||||
|
||||
def add_data(data_list, obj):
|
||||
from applications.extensions import db
|
||||
|
||||
for _data in data_list:
|
||||
dept = obj()
|
||||
for key, value in _data.items():
|
||||
|
||||
if isinstance(value, str) and date_str.match(value):
|
||||
value = datetime.strptime(value, "%Y-%m-%d %H:%M:%S")
|
||||
|
||||
setattr(dept, key, value)
|
||||
db.session.add(dept)
|
||||
db.session.commit()
|
||||
|
||||
|
||||
def register_script(app: Flask):
|
||||
@app.cli.command()
|
||||
def init_db():
|
||||
"""数据库初始化"""
|
||||
|
||||
# 创建化部门数据
|
||||
from applications.models import CompanyDepartment
|
||||
from applications.configs.init_data import cp_dept_data_list
|
||||
add_data(cp_dept_data_list, CompanyDepartment)
|
||||
|
||||
# 图片数据
|
||||
from applications.models import FilePhoto
|
||||
from applications.configs.init_data import file_photo_data_list
|
||||
|
||||
add_data(file_photo_data_list, FilePhoto)
|
||||
|
||||
# 初始化权限表数据
|
||||
from applications.models import RightsPower
|
||||
from applications.configs.init_data import rt_power_data_list
|
||||
|
||||
add_data(rt_power_data_list, RightsPower)
|
||||
# 初始化角色表
|
||||
from applications.models import RightsRole
|
||||
from applications.configs.init_data import rt_role_data_list
|
||||
|
||||
# 角色权限关系表
|
||||
from applications.extensions import db
|
||||
from applications.configs.init_data import rt_role_power_data_list
|
||||
for data in rt_role_power_data_list:
|
||||
db.session.execute('insert into rt_role_power VALUES (%s, %s, %s);' % tuple(data))
|
||||
db.session.commit()
|
||||
|
||||
add_data(rt_role_data_list, RightsRole)
|
||||
|
||||
# 管理员用户
|
||||
from applications.models import CompanyUser
|
||||
from applications.configs.init_data import cp_user_data_list
|
||||
|
||||
add_data(cp_user_data_list, CompanyUser)
|
||||
|
||||
# 用户角色表
|
||||
from applications.extensions import db
|
||||
from applications.configs.init_data import rt_user_role_data_list
|
||||
|
||||
for data in rt_user_role_data_list:
|
||||
db.session.execute('insert into rt_user_role VALUES (%s, %s, %s);' % tuple(data))
|
||||
db.session.commit()
|
||||
|
||||
@app.cli.command()
|
||||
def turn():
|
||||
"""清空数据库"""
|
||||
from applications.extensions import db
|
||||
db.drop_all()
|
||||
db.create_all()
|
||||
@@ -1,12 +0,0 @@
|
||||
import os
|
||||
from dotenv import load_dotenv
|
||||
|
||||
root_path = os.path.abspath(os.path.dirname(__file__)).split('applications')[0]
|
||||
dot_env_path = os.path.join(root_path, '.env')
|
||||
flask_env_path = os.path.join(root_path, '.flaskenv')
|
||||
|
||||
if os.path.exists(dot_env_path):
|
||||
load_dotenv(dot_env_path)
|
||||
|
||||
if os.path.exists(flask_env_path):
|
||||
load_dotenv(flask_env_path)
|
||||
@@ -1,15 +0,0 @@
|
||||
from flask import render_template
|
||||
|
||||
|
||||
def init_error_views(app):
|
||||
@app.errorhandler(403)
|
||||
def page_not_found(e):
|
||||
return render_template('errors/403.html'), 403
|
||||
|
||||
@app.errorhandler(404)
|
||||
def page_not_found(e):
|
||||
return render_template('errors/404.html'), 404
|
||||
|
||||
@app.errorhandler(500)
|
||||
def internal_server_error(e):
|
||||
return render_template('errors/500.html'), 500
|
||||
@@ -1,15 +0,0 @@
|
||||
from flask_login import LoginManager
|
||||
|
||||
|
||||
def init_login_manager(app):
|
||||
login_manager = LoginManager()
|
||||
login_manager.init_app(app)
|
||||
|
||||
login_manager.login_view = 'index.login'
|
||||
login_manager.login_message = u'请登录以访问此页面'
|
||||
|
||||
@login_manager.user_loader
|
||||
def load_user(user_id):
|
||||
from applications.models import CompanyUser
|
||||
user = CompanyUser.query.get(int(user_id))
|
||||
return user
|
||||
@@ -1,11 +0,0 @@
|
||||
from flask import Flask
|
||||
from flask_sqlalchemy import SQLAlchemy
|
||||
from flask_migrate import Migrate
|
||||
|
||||
db = SQLAlchemy()
|
||||
migrate = Migrate()
|
||||
|
||||
|
||||
def init_databases(app: Flask):
|
||||
db.init_app(app)
|
||||
migrate.init_app(app, db)
|
||||
@@ -1,7 +0,0 @@
|
||||
from flask import session
|
||||
|
||||
|
||||
def init_template_directives(app):
|
||||
@app.template_global()
|
||||
def authorize(power):
|
||||
return bool(power in session.get('permissions'))
|
||||
@@ -1,4 +0,0 @@
|
||||
from applications.models.file import FilePhoto
|
||||
from applications.models.log import LoggingModel
|
||||
from applications.models.rights import RightsPower, RightsRole, role_power, user_role
|
||||
from applications.models.users import CompanyDepartment, CompanyUser
|
||||
@@ -1,8 +0,0 @@
|
||||
from datetime import datetime
|
||||
|
||||
from applications.extensions import db
|
||||
|
||||
|
||||
class BaseModel(object):
|
||||
create_at = db.Column(db.DateTime, default=datetime.now, comment='创建时间')
|
||||
update_at = db.Column(db.DateTime, default=datetime.now, onupdate=datetime.now, comment='更新时间')
|
||||
@@ -1 +0,0 @@
|
||||
from .photo import FilePhoto
|
||||
@@ -1,12 +0,0 @@
|
||||
from applications.extensions import db
|
||||
|
||||
from ..base import BaseModel
|
||||
|
||||
|
||||
class FilePhoto(db.Model, BaseModel):
|
||||
__tablename__ = 'file_photo'
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
name = db.Column(db.String(255), nullable=False)
|
||||
href = db.Column(db.String(255))
|
||||
mime = db.Column(db.CHAR(50), nullable=False)
|
||||
size = db.Column(db.CHAR(30), nullable=False)
|
||||
@@ -1,16 +0,0 @@
|
||||
from flask_restful import fields
|
||||
|
||||
from applications.extensions import db
|
||||
from .base import BaseModel
|
||||
|
||||
|
||||
class LoggingModel(db.Model, BaseModel):
|
||||
__tablename__ = 'lg_logging'
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
method = db.Column(db.String(10))
|
||||
uid = db.Column(db.Integer, default=None)
|
||||
url = db.Column(db.String(255))
|
||||
desc = db.Column(db.Text)
|
||||
ip = db.Column(db.String(255))
|
||||
success = db.Column(db.Boolean, default=True)
|
||||
user_agent = db.Column(db.Text)
|
||||
@@ -1,19 +0,0 @@
|
||||
from applications.extensions import db
|
||||
from .power import RightsPower
|
||||
from .role import RightsRole
|
||||
|
||||
# 创建中间表
|
||||
user_role = db.Table(
|
||||
"rt_user_role", # 中间表名称
|
||||
db.Column("id", db.Integer, primary_key=True, autoincrement=True, comment='标识'), # 主键
|
||||
db.Column("user_id", db.Integer, db.ForeignKey("cp_user.id"), comment='用户编号'), # 属性 外键
|
||||
db.Column("role_id", db.Integer, db.ForeignKey("rt_role.id"), comment='角色编号'), # 属性 外键
|
||||
)
|
||||
|
||||
# 创建中间表
|
||||
role_power = db.Table(
|
||||
"rt_role_power", # 中间表名称
|
||||
db.Column("id", db.Integer, primary_key=True, autoincrement=True, comment='标识'), # 主键
|
||||
db.Column("power_id", db.Integer, db.ForeignKey("rt_power.id"), comment='用户编号'), # 属性 外键
|
||||
db.Column("role_id", db.Integer, db.ForeignKey("rt_role.id"), comment='角色编号'), # 属性 外键
|
||||
)
|
||||
@@ -1,18 +0,0 @@
|
||||
from applications.extensions import db
|
||||
from ..base import BaseModel
|
||||
|
||||
|
||||
class RightsPower(db.Model, BaseModel):
|
||||
__tablename__ = 'rt_power'
|
||||
id = db.Column(db.Integer, primary_key=True, comment='权限编号')
|
||||
name = db.Column(db.String(255), comment='权限名称')
|
||||
type = db.Column(db.SMALLINT, comment='权限类型')
|
||||
code = db.Column(db.String(30), comment='权限标识')
|
||||
url = db.Column(db.String(255), comment='权限路径')
|
||||
open_type = db.Column(db.String(10), comment='打开方式')
|
||||
parent_id = db.Column(db.Integer, db.ForeignKey("rt_power.id"), comment='父类编号')
|
||||
icon = db.Column(db.String(128), comment='图标')
|
||||
sort = db.Column(db.Integer, comment='排序')
|
||||
enable = db.Column(db.Boolean, comment='是否开启')
|
||||
|
||||
parent = db.relationship("RightsPower", remote_side=[id]) # 自关联
|
||||
@@ -1,17 +0,0 @@
|
||||
from flask_restful import fields
|
||||
|
||||
from applications.extensions import db
|
||||
from ..base import BaseModel
|
||||
|
||||
|
||||
class RightsRole(db.Model, BaseModel):
|
||||
__tablename__ = 'rt_role'
|
||||
id = db.Column(db.Integer, primary_key=True, comment='角色ID')
|
||||
name = db.Column(db.String(255), comment='角色名称')
|
||||
code = db.Column(db.String(255), comment='角色标识')
|
||||
enable = db.Column(db.Boolean, comment='是否启用')
|
||||
comment = db.Column(db.String(255), comment='备注')
|
||||
details = db.Column(db.String(255), comment='详情')
|
||||
sort = db.Column(db.Integer, comment='排序')
|
||||
|
||||
power = db.relationship('RightsPower', secondary="rt_role_power", backref=db.backref('role'))
|
||||
@@ -1,2 +0,0 @@
|
||||
from .dept import CompanyDepartment
|
||||
from .users import CompanyUser
|
||||
@@ -1,37 +0,0 @@
|
||||
from flask_restful import fields
|
||||
from applications.extensions import db
|
||||
from ..base import BaseModel
|
||||
|
||||
|
||||
class CompanyDepartment(db.Model, BaseModel):
|
||||
__tablename__ = 'cp_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="部门名称")
|
||||
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.Boolean, comment='状态(1开启,0关闭)')
|
||||
comment = db.Column(db.Text, comment="备注")
|
||||
address = db.Column(db.String(255), comment="详细地址")
|
||||
sort = db.Column(db.Integer, comment="排序")
|
||||
|
||||
@staticmethod
|
||||
def fields():
|
||||
"""
|
||||
定义模型的常用输出字段,新手请忽略。可以简化字段序列化操作,
|
||||
详细操作请查看 flask-restful marshal 的用法
|
||||
"""
|
||||
return {
|
||||
'deptId': fields.Integer(attribute="id"),
|
||||
'parentId': fields.Integer(attribute="parent_id"),
|
||||
'deptName': fields.String(attribute="dept_name"),
|
||||
'sort': fields.Integer,
|
||||
'leader': fields.String,
|
||||
'phone': fields.String,
|
||||
'email': fields.String,
|
||||
'status': fields.Boolean,
|
||||
'comment': fields.String,
|
||||
'address': fields.String,
|
||||
'create_at': fields.DateTime
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
from flask_login import UserMixin
|
||||
from werkzeug.security import generate_password_hash, check_password_hash
|
||||
from flask_restful import fields
|
||||
|
||||
from applications.extensions import db
|
||||
from ..base import BaseModel
|
||||
|
||||
|
||||
class CompanyUser(db.Model, UserMixin, BaseModel):
|
||||
__tablename__ = 'cp_user'
|
||||
id = db.Column(db.Integer, primary_key=True, autoincrement=True, comment='用户ID')
|
||||
username = db.Column(db.String(20), comment='用户名')
|
||||
realname = db.Column(db.String(20), comment='真实名字')
|
||||
mobile = db.Column(db.String(11), comment='电话号码')
|
||||
avatar = db.Column(db.String(255), comment='头像', default="/static/admin/admin/images/avatar.jpg")
|
||||
comment = db.Column(db.String(255), comment='备注')
|
||||
password_hash = db.Column(db.String(128), comment='哈希密码')
|
||||
enable = db.Column(db.Integer, default=0, comment='启用')
|
||||
dept_id = db.Column(db.Integer, comment='部门id')
|
||||
|
||||
role = db.relationship('RightsRole', secondary="rt_user_role", backref=db.backref('user'), lazy='dynamic')
|
||||
|
||||
def set_password(self, password):
|
||||
"""设置密码,对密码进行加密存储"""
|
||||
self.password_hash = generate_password_hash(password)
|
||||
|
||||
def validate_password(self, password):
|
||||
"""校验密码方法"""
|
||||
return check_password_hash(self.password_hash, password)
|
||||
@@ -1,7 +1,7 @@
|
||||
from flask import render_template, request
|
||||
|
||||
from applications.common.utils.rights import permission_required, view_logging_required
|
||||
from applications.models import CompanyDepartment
|
||||
from models import DepartmentModels
|
||||
from common.utils.rights import permission_required, view_logging_required
|
||||
from applications.view import index_bp
|
||||
|
||||
|
||||
@@ -24,5 +24,5 @@ def add():
|
||||
@permission_required("admin:dept:edit")
|
||||
def edit():
|
||||
dept_id = request.args.get("deptId", type=int)
|
||||
dept = CompanyDepartment.query.get(dept_id)
|
||||
dept = DepartmentModels.query.get(dept_id)
|
||||
return render_template('admin/department/dept_edit.html', dept=dept)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
from flask import render_template
|
||||
|
||||
from applications.view import index_bp
|
||||
from applications.common.utils.rights import view_logging_required, permission_required
|
||||
from common.utils.rights import view_logging_required, permission_required
|
||||
|
||||
|
||||
@index_bp.get('/file')
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
from flask import Blueprint, request, render_template
|
||||
from sqlalchemy import desc
|
||||
|
||||
from applications.common.utils.http import table_api
|
||||
from applications.common.utils.rights import permission_required
|
||||
from applications.models import LoggingModel
|
||||
from common.utils.http import table_api
|
||||
from common.utils.rights import permission_required
|
||||
from models import LogModel
|
||||
|
||||
logs_bp = Blueprint('logs', __name__, url_prefix='/logs')
|
||||
|
||||
@@ -19,9 +19,9 @@ def index():
|
||||
def login_log():
|
||||
page = request.args.get('page', type=int)
|
||||
limit = request.args.get('limit', type=int)
|
||||
log_paginate = LoggingModel.query.filter_by(
|
||||
log_paginate = LogModel.query.filter_by(
|
||||
url='/api/v1/passport/login').order_by(
|
||||
desc(LoggingModel.create_at)).paginate(
|
||||
desc(LogModel.create_at)).paginate(
|
||||
page=page, per_page=limit, error_out=False)
|
||||
data = [
|
||||
{
|
||||
@@ -47,9 +47,9 @@ def login_log():
|
||||
def operate_log():
|
||||
page = request.args.get('page', type=int)
|
||||
limit = request.args.get('limit', type=int)
|
||||
log_paginate = LoggingModel.query.filter(
|
||||
LoggingModel.url != '/api/v1/passport/login').order_by(
|
||||
desc(LoggingModel.create_at)).paginate(
|
||||
log_paginate = LogModel.query.filter(
|
||||
LogModel.url != '/api/v1/passport/login').order_by(
|
||||
desc(LogModel.create_at)).paginate(
|
||||
page=page, per_page=limit, error_out=False)
|
||||
data = [
|
||||
{
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
from flask import Blueprint, session, redirect, render_template, url_for
|
||||
from flask import session, redirect, render_template, url_for
|
||||
from flask_login import login_required, logout_user, current_user
|
||||
|
||||
from applications.common.gen_captcha import get_captcha_image
|
||||
from applications.common.utils.http import success_api
|
||||
from common.gen_captcha import get_captcha_image
|
||||
from common.utils.http import success_api
|
||||
|
||||
# 获取验证码
|
||||
from applications.view import index_bp
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
from flask import render_template
|
||||
|
||||
from applications.common.utils.rights import permission_required, view_logging_required
|
||||
from applications.models import RightsPower
|
||||
from common.utils.rights import permission_required, view_logging_required
|
||||
from models import RightModels
|
||||
from applications.view import index_bp
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ def rights_index():
|
||||
@view_logging_required
|
||||
@permission_required("admin:power:edit")
|
||||
def rights_edit(power_id):
|
||||
power = RightsPower.query.filter_by(id=power_id).first()
|
||||
power = RightModels.query.filter_by(id=power_id).first()
|
||||
icon = str(power.icon).split()
|
||||
if len(icon) == 2:
|
||||
icon = icon[1]
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
from flask import Blueprint, render_template
|
||||
|
||||
from applications.common.utils.rights import permission_required, view_logging_required
|
||||
from common.utils.rights import permission_required, view_logging_required
|
||||
|
||||
from applications.models import RightsRole
|
||||
from models import RoleModels
|
||||
|
||||
role_bp = Blueprint('role', __name__, url_prefix='/admin/role')
|
||||
|
||||
@@ -28,7 +28,7 @@ def power(role_id):
|
||||
@view_logging_required
|
||||
@permission_required("admin:role:edit")
|
||||
def role_editor(role_id):
|
||||
role = RightsRole.query.filter_by(id=role_id).first()
|
||||
role = RoleModels.query.filter_by(id=role_id).first()
|
||||
return render_template('admin/roles/roles_edit.html', role=role)
|
||||
|
||||
|
||||
|
||||
@@ -2,8 +2,8 @@ from flask import render_template
|
||||
from flask_login import login_required, current_user
|
||||
from sqlalchemy import desc
|
||||
|
||||
from applications.common.utils.rights import permission_required, view_logging_required
|
||||
from applications.models import LoggingModel, RightsRole, CompanyUser
|
||||
from common.utils.rights import permission_required, view_logging_required
|
||||
from models import LogModel, RoleModels, UserModels
|
||||
from . import index_bp
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ def users_main():
|
||||
@view_logging_required
|
||||
@permission_required("admin:user:add")
|
||||
def users_add_view():
|
||||
roles = RightsRole.query.all()
|
||||
roles = RoleModels.query.all()
|
||||
return render_template('admin/users/users_add.html', roles=roles)
|
||||
|
||||
|
||||
@@ -28,8 +28,8 @@ def users_add_view():
|
||||
@permission_required("admin:user:edit")
|
||||
def users_user_id_view(user_id):
|
||||
# 获取编辑用户信息
|
||||
user = CompanyUser.query.filter_by(id=user_id).first()
|
||||
roles = RightsRole.query.all()
|
||||
user = UserModels.query.filter_by(id=user_id).first()
|
||||
roles = RoleModels.query.all()
|
||||
checked_roles = []
|
||||
for r in user.role:
|
||||
checked_roles.append(r.id)
|
||||
@@ -39,8 +39,8 @@ def users_user_id_view(user_id):
|
||||
@index_bp.get('/users/center')
|
||||
@login_required
|
||||
def users_center():
|
||||
user_logs = LoggingModel.query.filter_by(url='/passport/login').filter_by(uid=current_user.id).order_by(
|
||||
desc(LoggingModel.create_at)).limit(10)
|
||||
user_logs = LogModel.query.filter_by(url='/passport/login').filter_by(uid=current_user.id).order_by(
|
||||
desc(LogModel.create_at)).limit(10)
|
||||
return render_template('admin/users/profile.html', user_info=current_user, user_logs=user_logs)
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user