Files
crawler-plugin/backend/utils/auth.py
T
2026-04-30 11:36:58 +08:00

114 lines
3.5 KiB
Python

"""
认证装饰器与 session 校验
"""
from functools import wraps
from flask import request, redirect, url_for, session, jsonify, g
from utils.db import get_db
def is_session_user_valid():
"""校验 session 中的 user_id 是否仍存在;不存在则清空 session。"""
uid = session.get('user_id')
if not uid:
return False
cached_user = getattr(g, '_current_user_row', None)
if cached_user and cached_user.get('id') == uid:
return True
try:
conn = get_db()
with conn.cursor() as cur:
cur.execute(
"SELECT id, username, is_admin, role, created_by_id FROM users WHERE id = %s",
(uid,)
)
row = cur.fetchone()
conn.close()
if not row:
session.clear()
return False
g._current_user_row = row
return True
except Exception:
session.clear()
return False
def get_current_admin_role():
"""返回当前登录用户的管理角色:super_admin / admin / None。"""
uid = session.get('user_id')
if not uid:
return None, None
try:
row = getattr(g, '_current_user_row', None)
if not row or row.get('id') != uid:
conn = get_db()
with conn.cursor() as cur:
cur.execute(
"SELECT id, username, is_admin, role, created_by_id FROM users WHERE id = %s",
(uid,)
)
row = cur.fetchone()
conn.close()
if not row:
return None, None
g._current_user_row = row
role = (row.get('role') or '').strip().lower()
if not role:
role = 'super_admin' if row.get('is_admin') and row.get('created_by_id') is None else (
'admin' if row.get('is_admin') else 'normal'
)
return role, row
except Exception:
return None, None
def is_current_user_admin():
role, _ = get_current_admin_role()
return role in ('super_admin', 'admin')
def _is_ajax_request():
if request.headers.get('X-Requested-With') == 'XMLHttpRequest':
return True
if request.path.startswith('/api/'):
return True
accept = (request.headers.get('Accept') or '').lower()
if 'application/json' in accept:
return True
return False
def login_required(f):
@wraps(f)
def decorated(*args, **kwargs):
if not session.get('user_id') or not is_session_user_valid():
if _is_ajax_request():
return jsonify({'success': False, 'error': '未登录'}), 401
return redirect(url_for('auth.login'))
return f(*args, **kwargs)
return decorated
def admin_required(f):
@wraps(f)
def decorated(*args, **kwargs):
if not session.get('user_id') or not is_session_user_valid():
if _is_ajax_request():
return jsonify({'success': False, 'error': '未登录'}), 401
return redirect(url_for('auth.login'))
try:
role, _ = get_current_admin_role()
if role not in ('super_admin', 'admin'):
if _is_ajax_request():
return jsonify({'success': False, 'error': '需要管理员权限'}), 403
return redirect(url_for('auth.login'))
except Exception as exc:
if _is_ajax_request():
return jsonify({'success': False, 'error': str(exc)}), 500
return redirect(url_for('auth.login'))
return f(*args, **kwargs)
return decorated