feat(admin): 添加用户管理相关文件

添加用户管理视图、API和状态管理文件
This commit is contained in:
张翔
2026-03-28 14:37:29 +08:00
commit 08ea5fbe98
1643 changed files with 255646 additions and 0 deletions
@@ -0,0 +1,201 @@
import json
import time
from typing import Optional, Dict, Any
from datetime import datetime, timedelta
from apitest.models.exceptions import AuthException
class AuthManager:
"""认证管理器"""
def __init__(self, base_url: str, credentials: Dict[str, str], logger):
"""初始化认证管理器
Args:
base_url: 基础URL
credentials: 认证凭据
logger: 日志记录器
"""
self.base_url = base_url.rstrip("/")
self.credentials = credentials
self.logger = logger
self._token: Optional[str] = None
self._token_expiry: Optional[datetime] = None
self._refresh_token: Optional[str] = None
self._login_endpoint: str = "/sys/auth/login"
def set_login_endpoint(self, endpoint: str):
"""设置登录端点
Args:
endpoint: 登录端点
"""
self._login_endpoint = endpoint
def login(self, login_endpoint: Optional[str] = None) -> Dict[str, Any]:
"""执行登录操作
Args:
login_endpoint: 登录端点,默认使用配置的端点
Returns:
登录响应数据
Raises:
AuthException: 登录失败时抛出
"""
endpoint = login_endpoint or self._login_endpoint
url = f"{self.base_url}{endpoint}"
self.logger.info(f"尝试登录: {url}")
try:
import requests
response = requests.post(
url,
json={
"username": self.credentials.get("username", ""),
"password": self.credentials.get("password", "")
},
timeout=10
)
if response.status_code == 200:
data = response.json()
if "data" in data and "token" in data["data"]:
self._token = data["data"]["token"]
self._refresh_token = data["data"].get("refreshToken")
expiry_seconds = data["data"].get("expiresIn", 3600)
self._token_expiry = datetime.now() + timedelta(seconds=expiry_seconds)
self.logger.info("登录成功")
return data
else:
raise AuthException("登录响应中未找到token")
else:
raise AuthException(f"登录失败: HTTP {response.status_code}")
except requests.RequestException as e:
raise AuthException(f"登录请求失败: {e}")
def get_token(self) -> Optional[str]:
"""获取当前token
Returns:
当前token,如果未登录则返回None
"""
return self._token
def set_token(self, token: str, expiry_seconds: int = 3600):
"""设置token
Args:
token: 认证令牌
expiry_seconds: 过期时间(秒),默认3600秒
"""
self._token = token
self._token_expiry = datetime.now() + timedelta(seconds=expiry_seconds)
self.logger.info("Token已设置")
def is_token_valid(self) -> bool:
"""检查token是否有效
Returns:
token是否有效
"""
if not self._token or not self._token_expiry:
return False
return datetime.now() < self._token_expiry
def refresh_token(self) -> bool:
"""刷新token
Returns:
刷新是否成功
"""
if not self._refresh_token:
self.logger.warning("没有可用的refresh token")
return False
try:
import requests
url = f"{self.base_url}/sys/auth/refresh"
response = requests.post(
url,
json={"refreshToken": self._refresh_token},
timeout=10
)
if response.status_code == 200:
data = response.json()
if "data" in data and "token" in data["data"]:
self._token = data["data"]["token"]
self._refresh_token = data["data"].get("refreshToken")
expiry_seconds = data["data"].get("expiresIn", 3600)
self._token_expiry = datetime.now() + timedelta(seconds=expiry_seconds)
self.logger.info("Token刷新成功")
return True
self.logger.warning("Token刷新失败,尝试重新登录")
return False
except Exception as e:
self.logger.error(f"Token刷新异常: {e}")
return False
def ensure_authenticated(self) -> str:
"""确保已认证,如果token过期则自动刷新或重新登录
Returns:
有效的token
Raises:
AuthException: 认证失败时抛出
"""
if not self._token:
self.login()
elif not self.is_token_valid():
if not self.refresh_token():
self.login()
if not self._token:
raise AuthException("无法获取有效的认证token")
return self._token
def logout(self):
"""登出"""
self._token = None
self._refresh_token = None
self._token_expiry = None
self.logger.info("已登出")
def get_auth_headers(self) -> Dict[str, str]:
"""获取认证请求头
Returns:
包含认证信息的请求头字典
"""
token = self.ensure_authenticated()
return {
"Authorization": f"Bearer {token}",
"Content-Type": "application/json"
}
def set_credentials(self, username: str, password: str):
"""设置认证凭据
Args:
username: 用户名
password: 密码
"""
self.credentials = {"username": username, "password": password}
self.logger.info("认证凭据已更新")