## 新增功能 ### Ubuntu 22.04初始化脚本 - 🚀 完整的系统环境初始化脚本 `ubuntu-22.04-init.sh` - 🛠️ 支持Docker、Java 21、Node.js、Python3、MySQL、Redis等全套环境 - 🔧 自动配置防火墙、系统参数优化 - 📁 标准化项目目录结构 `/opt/ljwx` - 📋 生成配置文件模板和维护脚本 ### ljwx-bigscreen FastAPI重构 - 🏗️ 新的FastAPI架构设计,支持异步高性能 - 📊 完整的业务逻辑分层:API -> Service -> Repository - 🎯 支持大屏主界面、个人界面、健康数据可视化 - 🔄 Redis缓存集成和数据库连接池 - 🎨 保留所有原有HTML模板和静态资源 ### 文档完善 - 📖 新增FastAPI重构进度文档 - 🏗️ 详细的项目架构分析 - 📋 完整的部署组件清单和依赖关系 ## 技术亮点 - **系统兼容性**: 专为Ubuntu 22.04优化的完整部署方案 - **架构现代化**: FastAPI异步框架替代传统Flask同步架构 - **企业级部署**: 13个服务组件的完整CI/CD + 业务系统 - **多架构支持**: linux/amd64 + linux/arm64双架构Docker支持 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
244 lines
6.6 KiB
Python
244 lines
6.6 KiB
Python
"""
|
|
API 依赖注入
|
|
提供通用的依赖项
|
|
"""
|
|
|
|
from typing import Generator, Optional
|
|
from fastapi import Depends, HTTPException, status, Request
|
|
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
|
|
from jose import JWTError, jwt
|
|
from sqlalchemy.ext.asyncio import AsyncSession
|
|
|
|
from app.core.database import get_write_db, get_read_db
|
|
from app.core.cache import get_cache
|
|
from app.base.redis import RedisClient
|
|
from app.base.mysql import MySQLClient
|
|
from app.base.user import UserService
|
|
from app.base.org import OrganizationService
|
|
from app.config.settings import get_settings
|
|
|
|
settings = get_settings()
|
|
security = HTTPBearer()
|
|
|
|
|
|
# 数据库依赖
|
|
async def get_mysql_client(
|
|
db: AsyncSession = Depends(get_write_db)
|
|
) -> MySQLClient:
|
|
"""获取 MySQL 客户端"""
|
|
return MySQLClient(db)
|
|
|
|
|
|
async def get_redis_client() -> RedisClient:
|
|
"""获取 Redis 客户端"""
|
|
return RedisClient()
|
|
|
|
|
|
# 服务依赖
|
|
async def get_user_service(
|
|
mysql_client: MySQLClient = Depends(get_mysql_client),
|
|
redis_client: RedisClient = Depends(get_redis_client)
|
|
) -> UserService:
|
|
"""获取用户服务"""
|
|
return UserService(mysql_client, redis_client)
|
|
|
|
|
|
async def get_org_service(
|
|
mysql_client: MySQLClient = Depends(get_mysql_client),
|
|
redis_client: RedisClient = Depends(get_redis_client)
|
|
) -> OrganizationService:
|
|
"""获取组织服务"""
|
|
return OrganizationService(mysql_client, redis_client)
|
|
|
|
|
|
# 认证依赖
|
|
def verify_token(credentials: HTTPAuthorizationCredentials = Depends(security)) -> dict:
|
|
"""验证 JWT Token"""
|
|
try:
|
|
payload = jwt.decode(
|
|
credentials.credentials,
|
|
settings.SECRET_KEY,
|
|
algorithms=["HS256"]
|
|
)
|
|
|
|
user_id: str = payload.get("sub")
|
|
if user_id is None:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_401_UNAUTHORIZED,
|
|
detail="Invalid authentication credentials",
|
|
headers={"WWW-Authenticate": "Bearer"},
|
|
)
|
|
|
|
return payload
|
|
|
|
except JWTError:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_401_UNAUTHORIZED,
|
|
detail="Invalid authentication credentials",
|
|
headers={"WWW-Authenticate": "Bearer"},
|
|
)
|
|
|
|
|
|
async def get_current_user(
|
|
token_payload: dict = Depends(verify_token),
|
|
user_service: UserService = Depends(get_user_service)
|
|
) -> dict:
|
|
"""获取当前用户"""
|
|
user_id = token_payload.get("sub")
|
|
|
|
user = await user_service.get_user_by_id(user_id)
|
|
if user is None:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_401_UNAUTHORIZED,
|
|
detail="User not found"
|
|
)
|
|
|
|
if user['status'] != 1:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_401_UNAUTHORIZED,
|
|
detail="User account is disabled"
|
|
)
|
|
|
|
return user
|
|
|
|
|
|
async def get_current_active_user(
|
|
current_user: dict = Depends(get_current_user)
|
|
) -> dict:
|
|
"""获取当前活跃用户"""
|
|
return current_user
|
|
|
|
|
|
# 权限依赖
|
|
def require_permissions(*permissions: str):
|
|
"""要求特定权限"""
|
|
async def permission_checker(
|
|
current_user: dict = Depends(get_current_active_user)
|
|
) -> dict:
|
|
# 这里实现权限检查逻辑
|
|
# 简化版本:检查用户角色
|
|
user_roles = current_user.get('roles', [])
|
|
|
|
# 管理员拥有所有权限
|
|
if 'admin' in user_roles:
|
|
return current_user
|
|
|
|
# 检查特定权限
|
|
# 实际项目中需要实现更复杂的权限验证逻辑
|
|
|
|
return current_user
|
|
|
|
return permission_checker
|
|
|
|
|
|
def require_customer_access(customer_id: str):
|
|
"""要求客户访问权限"""
|
|
async def customer_checker(
|
|
current_user: dict = Depends(get_current_active_user)
|
|
) -> dict:
|
|
user_customer_id = current_user.get('customer_id')
|
|
|
|
# 检查用户是否属于该客户
|
|
if user_customer_id != customer_id:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_403_FORBIDDEN,
|
|
detail="Access denied: insufficient customer permissions"
|
|
)
|
|
|
|
return current_user
|
|
|
|
return customer_checker
|
|
|
|
|
|
# 分页依赖
|
|
class PaginationParams:
|
|
"""分页参数"""
|
|
def __init__(
|
|
self,
|
|
page: int = 1,
|
|
page_size: int = 20,
|
|
max_page_size: int = 100
|
|
):
|
|
if page < 1:
|
|
page = 1
|
|
if page_size < 1:
|
|
page_size = 20
|
|
if page_size > max_page_size:
|
|
page_size = max_page_size
|
|
|
|
self.page = page
|
|
self.page_size = page_size
|
|
self.offset = (page - 1) * page_size
|
|
|
|
|
|
def get_pagination_params(
|
|
page: int = 1,
|
|
page_size: int = 20
|
|
) -> PaginationParams:
|
|
"""获取分页参数"""
|
|
return PaginationParams(page, page_size)
|
|
|
|
|
|
# 请求上下文
|
|
async def get_request_context(request: Request) -> dict:
|
|
"""获取请求上下文信息"""
|
|
return {
|
|
'ip_address': request.client.host,
|
|
'user_agent': request.headers.get('user-agent'),
|
|
'request_id': request.headers.get('x-request-id'),
|
|
'timestamp': request.state.__dict__.get('start_time')
|
|
}
|
|
|
|
|
|
# 业务服务依赖
|
|
async def get_alert_service(
|
|
mysql_client: MySQLClient = Depends(get_mysql_client),
|
|
redis_client: RedisClient = Depends(get_redis_client)
|
|
):
|
|
"""获取告警服务"""
|
|
from app.business.alert import AlertService
|
|
return AlertService(mysql_client, redis_client)
|
|
|
|
|
|
async def get_health_service(
|
|
mysql_client: MySQLClient = Depends(get_mysql_client),
|
|
redis_client: RedisClient = Depends(get_redis_client)
|
|
):
|
|
"""获取健康数据服务"""
|
|
from app.business.health_data import HealthDataService
|
|
return HealthDataService(mysql_client, redis_client)
|
|
|
|
|
|
# 缓存依赖
|
|
async def get_cache_client():
|
|
"""获取缓存客户端"""
|
|
return get_cache()
|
|
|
|
|
|
# 可选认证(某些接口可以匿名访问)
|
|
async def get_optional_current_user(
|
|
credentials: Optional[HTTPAuthorizationCredentials] = Depends(
|
|
HTTPBearer(auto_error=False)
|
|
),
|
|
user_service: UserService = Depends(get_user_service)
|
|
) -> Optional[dict]:
|
|
"""获取可选的当前用户(支持匿名访问)"""
|
|
if not credentials:
|
|
return None
|
|
|
|
try:
|
|
payload = jwt.decode(
|
|
credentials.credentials,
|
|
settings.SECRET_KEY,
|
|
algorithms=["HS256"]
|
|
)
|
|
|
|
user_id = payload.get("sub")
|
|
if user_id:
|
|
user = await user_service.get_user_by_id(user_id)
|
|
if user and user['status'] == 1:
|
|
return user
|
|
except JWTError:
|
|
pass
|
|
|
|
return None |