提交登录修改

This commit is contained in:
super
2026-05-23 18:32:45 +08:00
parent 2e2de02476
commit 1e087c1aae
52 changed files with 2139 additions and 1572 deletions

View File

@@ -1,5 +1,5 @@
"""
公共模块:数据库连接、初始化、会话校验、装饰器、模板渲染
公共模块:数据库连接、初始化、JWT 鉴权装饰器、模板渲染
供各蓝图复用
"""
import os
@@ -8,18 +8,19 @@ from datetime import timedelta
from functools import wraps
import pymysql
from flask import request, redirect, url_for, session, jsonify, render_template, render_template_string
from flask import request, redirect, url_for, jsonify, render_template, render_template_string, g
from config import mysql_host, mysql_user, mysql_password, mysql_database
from jwt_util import parse_token, get_token_from_request
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
STATIC_DIR = os.path.join(BASE_DIR, 'static')
ASSETS_DIR = os.path.join(BASE_DIR, 'assets')
WEB_SOURCE_DIR = os.path.join(BASE_DIR, 'web_source')
TEMPLATE_FALLBACK_DIRS = (
WEB_SOURCE_DIR,
os.path.join(WEB_SOURCE_DIR, 'templates_backup'),
)
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
STATIC_DIR = os.path.join(BASE_DIR, 'static')
ASSETS_DIR = os.path.join(BASE_DIR, 'assets')
WEB_SOURCE_DIR = os.path.join(BASE_DIR, 'web_source')
TEMPLATE_FALLBACK_DIRS = (
WEB_SOURCE_DIR,
os.path.join(WEB_SOURCE_DIR, 'templates_backup'),
)
def get_db():
@@ -35,13 +36,13 @@ def get_db():
def _render_html(template_name: str, **context):
"""读取 HTML 模板:若为加密文件则先解密,再渲染。未加密或解密失败时按明文渲染。"""
path = next(
(candidate for candidate in (os.path.join(base_path, template_name) for base_path in TEMPLATE_FALLBACK_DIRS)
if os.path.isfile(candidate)),
None,
)
if path is None:
return render_template(template_name, **context)
path = next(
(candidate for candidate in (os.path.join(base_path, template_name) for base_path in TEMPLATE_FALLBACK_DIRS)
if os.path.isfile(candidate)),
None,
)
if path is None:
return render_template(template_name, **context)
with open(path, "rb") as f:
raw = f.read()
try:
@@ -54,13 +55,13 @@ def _render_html(template_name: str, **context):
def _render_html_new(template_name: str, **context):
"""读取 HTML 模板:若为加密文件则先解密,再渲染。未加密或解密失败时按明文渲染。"""
path = next(
(candidate for candidate in (os.path.join(base_path, template_name) for base_path in TEMPLATE_FALLBACK_DIRS)
if os.path.isfile(candidate)),
None,
)
if path is None:
return render_template(template_name, **context)
path = next(
(candidate for candidate in (os.path.join(base_path, template_name) for base_path in TEMPLATE_FALLBACK_DIRS)
if os.path.isfile(candidate)),
None,
)
if path is None:
return render_template(template_name, **context)
with open(path, "rb") as f:
raw = f.read()
try:
@@ -72,9 +73,36 @@ def _render_html_new(template_name: str, **context):
def _resolve_jwt_user():
"""从 Authorization/cookie 解析 JWT命中后写入 flask.g 缓存。无效返回 None。"""
cached = getattr(g, "_aiimage_user", None)
if cached is not None:
return cached or None
token = get_token_from_request()
payload = parse_token(token) if token else None
if not payload:
g._aiimage_user = False
return None
g._aiimage_user = payload
g.aiimage_user_id = payload.get("user_id")
g.aiimage_username = payload.get("username") or ""
g.aiimage_device_id = payload.get("device_id") or ""
return payload
def current_user_id():
user = _resolve_jwt_user()
return user.get("user_id") if user else None
def current_username():
user = _resolve_jwt_user()
return user.get("username") if user else ""
def _is_session_user_valid():
"""校验 session 中的 user_id 是否在数据库中仍存在;不存在则清除 session 并返回 False"""
uid = session.get('user_id')
"""兼容旧调用:判断当前 JWT 用户是否仍存在于数据库。"""
uid = current_user_id()
if not uid:
return False
try:
@@ -83,23 +111,22 @@ def _is_session_user_valid():
cur.execute("SELECT id FROM users WHERE id = %s", (uid,))
row = cur.fetchone()
conn.close()
if not row:
session.clear()
return False
return True
return bool(row)
except Exception:
session.clear()
return False
def _get_current_admin_role():
"""获取当前登录用户的管理角色super_admin / admin / None非管理员"""
uid = current_user_id()
if not uid:
return None, None
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",
(session['user_id'],)
(uid,)
)
row = cur.fetchone()
conn.close()
@@ -110,13 +137,19 @@ def _get_current_admin_role():
return None, None
def _unauthorized_response():
if request.headers.get('X-Requested-With') == 'XMLHttpRequest' \
or request.path.startswith('/api/') \
or 'application/json' in (request.headers.get('Accept') or ''):
return jsonify({'success': False, 'error': '未登录'}), 401
return redirect(url_for('auth.login'))
def login_required(f):
@wraps(f)
def decorated(*args, **kwargs):
if not session.get('user_id') or not _is_session_user_valid():
if request.headers.get('X-Requested-With') == 'XMLHttpRequest':
return jsonify({'success': False, 'error': '未登录'}), 401
return redirect(url_for('auth.login'))
if not current_user_id():
return _unauthorized_response()
return f(*args, **kwargs)
return decorated
@@ -124,22 +157,24 @@ def login_required(f):
def admin_required(f):
@wraps(f)
def decorated(*args, **kwargs):
if not session.get('user_id'):
if request.headers.get('X-Requested-With') == 'XMLHttpRequest':
return jsonify({'success': False, 'error': '未登录'}), 401
return redirect(url_for('auth.login'))
uid = current_user_id()
if not uid:
return _unauthorized_response()
try:
conn = get_db()
with conn.cursor() as cur:
cur.execute("SELECT is_admin, role FROM users WHERE id = %s", (session['user_id'],))
cur.execute("SELECT is_admin, role FROM users WHERE id = %s", (uid,))
row = cur.fetchone()
conn.close()
if not row or not row.get('is_admin'):
if request.headers.get('X-Requested-With') == 'XMLHttpRequest':
if request.headers.get('X-Requested-With') == 'XMLHttpRequest' \
or request.path.startswith('/api/') \
or 'application/json' in (request.headers.get('Accept') or ''):
return jsonify({'success': False, 'error': '需要管理员权限'}), 403
return redirect(url_for('main.home'))
except Exception as e:
if request.headers.get('X-Requested-With') == 'XMLHttpRequest':
if request.headers.get('X-Requested-With') == 'XMLHttpRequest' \
or request.path.startswith('/api/'):
return jsonify({'success': False, 'error': str(e)}), 500
return redirect(url_for('main.home'))
return f(*args, **kwargs)