agent-Specialization/server/auth_helpers.py
JOJO a2cf547400 feat(i18n): 后端用户可见消息国际化(zh/en 双语 + ui_locale 偏好持久化)
- 新增 modules/i18n.py:tr() + 进程级语言缓存 + modules/i18n_messages/ 域文案包自动聚合
- 新增 29 个域文案包,共 1153 条双语 key;90+ 源文件 1146 处用户可见消息 tr 化
- ui_locale 存入 personalization.json(用户级共享),前后端双向同步
- 前端匹配点双语兼容(history/shared/ChatArea/taskPolling/upload 等正则)
- 修复语言判等陷阱:审批等待加稳定 code 字段;conversation.py 不存在判等改双语 helper
- 边界:日志/prompt 注入/子智能体工具回填/容器内嵌脚本不迁移
2026-08-29 07:58:29 +08:00

112 lines
3.2 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""认证与角色相关基础函数,供各模块复用。"""
from __future__ import annotations
from functools import wraps
from typing import Optional, Any, Dict
from flask import session, redirect, jsonify
from modules import admin_policy_manager
from .utils_common import debug_log
from . import state
from modules.i18n import tr
def is_logged_in() -> bool:
username = (session.get('username') or '').strip().lower()
if not username:
return False
nonce = session.get('login_nonce')
if not nonce:
return False
pool = state.active_login_nonces.get(username) or set()
return nonce in pool
def login_required(view_func):
@wraps(view_func)
def wrapped(*args, **kwargs):
if not is_logged_in():
return redirect('/login')
return view_func(*args, **kwargs)
return wrapped
def api_login_required(view_func):
@wraps(view_func)
def wrapped(*args, **kwargs):
if not is_logged_in():
return jsonify({"error": "Unauthorized"}), 401
return view_func(*args, **kwargs)
return wrapped
def get_current_username() -> Optional[str]:
return session.get('username')
def get_current_user_record():
username = get_current_username()
if not username:
return None
return state.user_manager.get_user(username)
def get_current_user_role(record=None) -> str:
role = session.get('role')
if role:
return role
if record is None:
record = get_current_user_record()
return (record.role if record and record.role else 'user')
def is_admin_user(record=None) -> bool:
role = get_current_user_role(record)
return isinstance(role, str) and role.lower() == 'admin'
def resolve_admin_policy(record=None) -> Dict[str, Any]:
"""获取当前用户生效的管理员策略。"""
if record is None:
record = get_current_user_record()
username = record.username if record else None
role = get_current_user_role(record)
invite_code = getattr(record, "invite_code", None)
try:
return admin_policy_manager.get_effective_policy(username, role, invite_code)
except Exception as exc:
debug_log(f"[admin_policy] 加载失败: {exc}")
return admin_policy_manager.get_effective_policy(username, role, invite_code)
def admin_required(view_func):
@wraps(view_func)
def wrapped(*args, **kwargs):
# host 模式下可能不存在 users.json 记录(如 username=host
# 但 session.role 已是 admin此时仍应允许访问管理页。
if not is_admin_user():
return redirect('/new')
return view_func(*args, **kwargs)
return wrapped
def admin_api_required(view_func):
@wraps(view_func)
def wrapped(*args, **kwargs):
if not is_admin_user():
return jsonify({"success": False, "error": tr("auth.admin_required")}), 403
return view_func(*args, **kwargs)
return wrapped
__all__ = [
"is_logged_in",
"login_required",
"api_login_required",
"get_current_username",
"get_current_user_record",
"get_current_user_role",
"is_admin_user",
"resolve_admin_policy",
"admin_required",
"admin_api_required",
]