diff --git a/applications/api/system/passport.py b/applications/api/system/passport.py index 05e14dd..46d0de1 100644 --- a/applications/api/system/passport.py +++ b/applications/api/system/passport.py @@ -3,9 +3,9 @@ from flask import session, redirect, url_for, request from flask_login import current_user, login_user from flask_restful import Resource, reqparse -from applications.common.admin_log import login_log, admin_log 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 @@ -41,9 +41,10 @@ class Login(Resource): # 登录 login_user(user) # 记录登录日志 - login_log(request, uid=user.id, is_access=True) + record_logging() + # 存入权限 add_auth_session() return success_api(msg="登录成功") - login_log(request, uid=user.id, is_access=False) + record_logging() return fail_api(msg="用户名或密码错误") diff --git a/applications/api/users/user.py b/applications/api/users/user.py index 350b758..1015f26 100644 --- a/applications/api/users/user.py +++ b/applications/api/users/user.py @@ -6,14 +6,14 @@ from sqlalchemy import desc from applications.common.utils.http import fail_api, success_api, table_api from applications.common.utils.rights import authorize from applications.extensions import db -from applications.models import AdminLog +from applications.models import LoggingModel from applications.models import CompanyUser, RightsRole, CompanyDepartment def get_current_user_logs(): """ 获取当前用户日志 """ - log = AdminLog.query.filter_by(url='/passport/login').filter_by(uid=current_user.id).order_by( - desc(AdminLog.create_at)).limit(10) + log = LoggingModel.query.filter_by(url='/passport/login').filter_by(uid=current_user.id).order_by( + desc(LoggingModel.create_at)).limit(10) return log diff --git a/applications/common/admin_log.py b/applications/common/admin_log.py deleted file mode 100644 index 1ef10dc..0000000 --- a/applications/common/admin_log.py +++ /dev/null @@ -1,56 +0,0 @@ -from flask_login import current_user - -from applications.extensions import db -from applications.models import AdminLog - - -def login_log(request, uid, is_access): - info = { - 'method': request.method, - 'url': request.path, - 'ip': request.remote_addr, - 'user_agent': request.headers.get('User-Agent'), - 'desc': request.form.get('username'), - 'uid': uid, - 'success': int(is_access) - - } - log = AdminLog( - url=info.get('url'), - ip=info.get('ip'), - user_agent=info.get('user_agent'), - desc=info.get('desc'), - uid=info.get('uid'), - method=info.get('method'), - success=info.get('success') - ) - db.session.add(log) - db.session.flush() - db.session.commit() - return log.id - - -def admin_log(request, is_access): - 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': int(is_access) - - } - log = AdminLog( - url=info.get('url'), - ip=info.get('ip'), - user_agent=info.get('user_agent'), - desc=info.get('desc'), - uid=info.get('uid'), - method=info.get('method'), - success=info.get('success') - ) - db.session.add(log) - db.session.commit() - - return log.id diff --git a/applications/common/utils/rights.py b/applications/common/utils/rights.py index 2e4f8cc..f7f7286 100644 --- a/applications/common/utils/rights.py +++ b/applications/common/utils/rights.py @@ -1,7 +1,64 @@ +import typing as t from functools import wraps + from flask import abort, request, jsonify, session from flask_login import login_required -from applications.common.admin_log import admin_log +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 def authorize(power: str, log: bool = False): @@ -11,17 +68,15 @@ def authorize(power: str, log: bool = False): def wrapper(*args, **kwargs): if power not in session.get('permissions'): if log: - admin_log(request=request, is_access=False) + record_logging() if request.method == 'GET': abort(403) else: return jsonify(success=False, msg="权限不足!") if log: - admin_log(request=request, is_access=True) + record_logging() return func(*args, **kwargs) return wrapper return decorator - - diff --git a/applications/models/__init__.py b/applications/models/__init__.py index 70db914..093698a 100644 --- a/applications/models/__init__.py +++ b/applications/models/__init__.py @@ -1,4 +1,4 @@ from applications.models.file import FilePhoto -from applications.models.log import AdminLog +from applications.models.log import LoggingModel from applications.models.rights import RightsPower, RightsRole, role_power, user_role from applications.models.users import CompanyDepartment, CompanyUser diff --git a/applications/models/log.py b/applications/models/log.py index 80c5733..6e44dba 100644 --- a/applications/models/log.py +++ b/applications/models/log.py @@ -2,14 +2,13 @@ from applications.extensions import db from .base import BaseModel -class AdminLog(db.Model, BaseModel): - __tablename__ = 'admin_admin_log' +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) + 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.Integer) + success = db.Column(db.Boolean, default=True) user_agent = db.Column(db.Text) - diff --git a/applications/view/department.py b/applications/view/department.py index 15ebe65..d6c4d7d 100644 --- a/applications/view/department.py +++ b/applications/view/department.py @@ -1,24 +1,27 @@ from flask import render_template, request -from applications.common.utils.rights import authorize +from applications.common.utils.rights import permission_required, view_logging_required from applications.models import CompanyDepartment from applications.view import index_bp @index_bp.get('/dept') -@authorize("admin:dept:main", log=True) +@view_logging_required +@permission_required("admin:dept:main") def dept_index(): return render_template('admin/department/dept.html') @index_bp.get('/dept/add') -@authorize("admin:dept:add", log=True) +@view_logging_required +@permission_required("admin:dept:add") def add(): return render_template('admin/department/dept_add.html') @index_bp.get('/dept/edit') -@authorize("admin:dept:edit", log=True) +@view_logging_required +@permission_required("admin:dept:edit") def edit(): dept_id = request.args.get("deptId", type=int) dept = CompanyDepartment.query.get(dept_id) diff --git a/applications/view/file.py b/applications/view/file.py index 6a9b1d4..7226c88 100644 --- a/applications/view/file.py +++ b/applications/view/file.py @@ -1,18 +1,18 @@ from flask import render_template from applications.view import index_bp -from applications.common.utils.rights import authorize +from applications.common.utils.rights import authorize, view_logging_required, permission_required -# 图片管理 @index_bp.get('/file') -@authorize("admin:file:main", log=True) +@view_logging_required +@permission_required("admin:file:main") def file_index(): return render_template('admin/file/photo.html') -# 图片管理 @index_bp.get('/file/photo/add') -@authorize("admin:file:main", log=True) +@view_logging_required +@permission_required("admin:file:main") def file_photo_add(): return render_template('admin/file/photo_add.html') diff --git a/applications/view/logs_view.py b/applications/view/logs_view.py index 1022e84..c9ef724 100644 --- a/applications/view/logs_view.py +++ b/applications/view/logs_view.py @@ -4,26 +4,26 @@ from flask_restful import marshal from applications.common.serialization import log_fields from applications.common.utils.http import table_api -from applications.common.utils.rights import authorize -from applications.models import AdminLog +from applications.common.utils.rights import authorize, permission_required +from applications.models import LoggingModel logs_bp = Blueprint('logs', __name__, url_prefix='/logs') @logs_bp.get('/') -@authorize("admin:log:main") +@permission_required("admin:log:main") def index(): return render_template('admin/logs_temp/main.html') @logs_bp.get('/login_log') -@authorize("admin:log:main") +@permission_required("admin:log:main") def login_log(): page = request.args.get('page', type=int) limit = request.args.get('limit', type=int) - log_paginate = AdminLog.query.filter_by( + log_paginate = LoggingModel.query.filter_by( url='/api/v1/passport/login').order_by( - desc(AdminLog.create_at)).paginate( + desc(LoggingModel.create_at)).paginate( page=page, per_page=limit, error_out=False) data = marshal(log_paginate.items, log_fields) @@ -31,13 +31,13 @@ def login_log(): @logs_bp.get('/access_log') -@authorize("admin:log:main") +@permission_required("admin:log:main") def operate_log(): page = request.args.get('page', type=int) limit = request.args.get('limit', type=int) - log_paginate = AdminLog.query.filter( - AdminLog.url != '/api/v1/passport/login').order_by( - desc(AdminLog.create_at)).paginate( + log_paginate = LoggingModel.query.filter( + LoggingModel.url != '/api/v1/passport/login').order_by( + desc(LoggingModel.create_at)).paginate( page=page, per_page=limit, error_out=False) data = marshal(log_paginate.items, log_fields) return table_api(data=data, count=log_paginate.total, code=0) diff --git a/applications/view/rights.py b/applications/view/rights.py index c7c2dab..ee53279 100644 --- a/applications/view/rights.py +++ b/applications/view/rights.py @@ -1,18 +1,20 @@ from flask import render_template -from applications.common.utils.rights import authorize +from applications.common.utils.rights import authorize, permission_required, view_logging_required from applications.models import RightsPower from applications.view import index_bp @index_bp.get('/rights/') -@authorize("admin:power:main", log=True) +@view_logging_required +@permission_required("admin:power:main") def rights_index(): return render_template('admin/rights/rights.html') @index_bp.get('/rights/power/') -@authorize("admin:power:edit", log=True) +@view_logging_required +@permission_required("admin:power:edit") def rights_edit(power_id): power = RightsPower.query.filter_by(id=power_id).first() icon = str(power.icon).split() @@ -24,6 +26,7 @@ def rights_edit(power_id): @index_bp.get('/rights/add') -@authorize("admin:power:main", log=True) +@view_logging_required +@permission_required("admin:power:main") def rights_add(): return render_template('admin/rights/rights_add.html') diff --git a/applications/view/roles.py b/applications/view/roles.py index 29f2384..e665950 100644 --- a/applications/view/roles.py +++ b/applications/view/roles.py @@ -1,6 +1,6 @@ from flask import Blueprint, render_template -from applications.common.utils.rights import authorize +from applications.common.utils.rights import authorize, permission_required, view_logging_required from applications.models import RightsRole @@ -9,27 +9,31 @@ role_bp = Blueprint('role', __name__, url_prefix='/admin/role') # 角色而管理 @role_bp.get('/') -@authorize("admin:role:main", log=True) +@view_logging_required +@permission_required("admin:role:main") def main(): return render_template('admin/roles/roles.html') # 角色授权操作 @role_bp.get('/power/') -@authorize("admin:role:power", log=True) +@view_logging_required +@permission_required("admin:role:power") def power(role_id): return render_template('admin/roles/roles_power.html', role_id=role_id) # 角色编辑 -@authorize("admin:role:edit", log=True) @role_bp.get('/edit/') +@view_logging_required +@permission_required("admin:role:edit") def role_editor(role_id): role = RightsRole.query.filter_by(id=role_id).first() return render_template('admin/roles/roles_edit.html', role=role) -@authorize("admin:role:edit", log=True) @role_bp.get('/add') +@view_logging_required +@permission_required("admin:role:edit") def role_add(): return render_template('admin/roles/roles_add.html') diff --git a/applications/view/users.py b/applications/view/users.py index 7bb6e8d..f6e21bb 100644 --- a/applications/view/users.py +++ b/applications/view/users.py @@ -2,28 +2,30 @@ from flask import render_template from flask_login import login_required, current_user from sqlalchemy import desc -from applications.common.utils.rights import authorize -from applications.models import AdminLog, RightsRole, CompanyUser +from applications.common.utils.rights import authorize, permission_required, view_logging_required +from applications.models import LoggingModel, RightsRole, CompanyUser from . import index_bp # 用户增加 @index_bp.get('/users/') -@authorize("admin:user:main", log=True) +@view_logging_required +@permission_required("admin:user:main") def users_main(): return render_template('admin/users/users.html') -@index_bp.get('/users/center') -@login_required -def users_center(): - user_logs = AdminLog.query.filter_by(url='/passport/login').filter_by(uid=current_user.id).order_by( - desc(AdminLog.create_at)).limit(10) - return render_template('admin/users/profile.html', user_info=current_user, user_logs=user_logs) +@index_bp.get('/users/add') +@view_logging_required +@permission_required("admin:user:add") +def users_add_view(): + roles = RightsRole.query.all() + return render_template('admin/users/users_add.html', roles=roles) @index_bp.get('/users/') -@authorize("admin:user:edit", log=True) +@view_logging_required +@permission_required("admin:user:edit") def users_user_id_view(user_id): # 获取编辑用户信息 user = CompanyUser.query.filter_by(id=user_id).first() @@ -34,12 +36,14 @@ def users_user_id_view(user_id): return render_template('admin/users/users_edit.html', user=user, roles=roles, checked_roles=checked_roles) +@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) + return render_template('admin/users/profile.html', user_info=current_user, user_logs=user_logs) + + @index_bp.get('/users/avatar') def users_avatar_view(): return render_template('admin/users/profile_avatar.html') - - -@index_bp.get('/users/add') -def users_add_view(): - roles = RightsRole.query.all() - return render_template('admin/users/users_add.html', roles=roles)