测试并修复api导入路径错误
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
from fastapi import APIRouter, Request, Depends
|
||||
from typing import Any, List, Dict, Union
|
||||
from app.services.tjnetwork import *
|
||||
from app.api.v1.endpoints.auth import verify_token
|
||||
from app.auth.dependencies import get_current_user as verify_token
|
||||
from app.infra.cache.redis_client import redis_client, encode_datetime, decode_datetime
|
||||
import msgpack
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@ from app.infra.db.timescaledb import router as timescaledb_router
|
||||
api_router = APIRouter()
|
||||
|
||||
# Core Services
|
||||
api_router.include_router(auth.router, tags=["Auth"])
|
||||
api_router.include_router(auth.router, prefix="/auth", tags=["Auth"])
|
||||
api_router.include_router(user_management.router, prefix="/users", tags=["User Management"]) # 新增
|
||||
api_router.include_router(audit.router, prefix="/audit", tags=["Audit Logs"]) # 新增
|
||||
api_router.include_router(project.router, tags=["Project"])
|
||||
|
||||
@@ -9,31 +9,34 @@ from app.infra.db.postgresql.database import Database
|
||||
|
||||
oauth2_scheme = OAuth2PasswordBearer(tokenUrl=f"{settings.API_V1_STR}/auth/login")
|
||||
|
||||
|
||||
# 数据库依赖
|
||||
async def get_db(request: Request) -> Database:
|
||||
"""
|
||||
获取数据库实例
|
||||
|
||||
|
||||
从 FastAPI app.state 中获取在启动时初始化的数据库连接
|
||||
"""
|
||||
if not hasattr(request.app.state, "db"):
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_503_SERVICE_UNAVAILABLE,
|
||||
detail="Database not initialized"
|
||||
detail="Database not initialized",
|
||||
)
|
||||
return request.app.state.db
|
||||
|
||||
|
||||
async def get_user_repository(db: Database = Depends(get_db)) -> UserRepository:
|
||||
"""获取用户仓储实例"""
|
||||
return UserRepository(db)
|
||||
|
||||
|
||||
async def get_current_user(
|
||||
token: str = Depends(oauth2_scheme),
|
||||
user_repo: UserRepository = Depends(get_user_repository)
|
||||
user_repo: UserRepository = Depends(get_user_repository),
|
||||
) -> UserInDB:
|
||||
"""
|
||||
获取当前登录用户
|
||||
|
||||
|
||||
从 JWT Token 中解析用户信息,并从数据库验证
|
||||
"""
|
||||
credentials_exception = HTTPException(
|
||||
@@ -41,32 +44,35 @@ async def get_current_user(
|
||||
detail="Could not validate credentials",
|
||||
headers={"WWW-Authenticate": "Bearer"},
|
||||
)
|
||||
|
||||
|
||||
try:
|
||||
payload = jwt.decode(token, settings.SECRET_KEY, algorithms=[settings.ALGORITHM])
|
||||
payload = jwt.decode(
|
||||
token, settings.SECRET_KEY, algorithms=[settings.ALGORITHM]
|
||||
)
|
||||
username: str = payload.get("sub")
|
||||
token_type: str = payload.get("type", "access")
|
||||
|
||||
|
||||
if username is None:
|
||||
raise credentials_exception
|
||||
|
||||
|
||||
if token_type != "access":
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_401_UNAUTHORIZED,
|
||||
detail="Invalid token type. Access token required.",
|
||||
headers={"WWW-Authenticate": "Bearer"},
|
||||
)
|
||||
|
||||
|
||||
except JWTError:
|
||||
raise credentials_exception
|
||||
|
||||
|
||||
# 从数据库获取用户
|
||||
user = await user_repo.get_user_by_username(username)
|
||||
if user is None:
|
||||
raise credentials_exception
|
||||
|
||||
|
||||
return user
|
||||
|
||||
|
||||
async def get_current_active_user(
|
||||
current_user: UserInDB = Depends(get_current_user),
|
||||
) -> UserInDB:
|
||||
@@ -75,11 +81,11 @@ async def get_current_active_user(
|
||||
"""
|
||||
if not current_user.is_active:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_403_FORBIDDEN,
|
||||
detail="Inactive user"
|
||||
status_code=status.HTTP_403_FORBIDDEN, detail="Inactive user"
|
||||
)
|
||||
return current_user
|
||||
|
||||
|
||||
async def get_current_superuser(
|
||||
current_user: UserInDB = Depends(get_current_user),
|
||||
) -> UserInDB:
|
||||
@@ -89,6 +95,6 @@ async def get_current_superuser(
|
||||
if not current_user.is_superuser:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_403_FORBIDDEN,
|
||||
detail="Not enough privileges. Superuser access required."
|
||||
detail="Not enough privileges. Superuser access required.",
|
||||
)
|
||||
return current_user
|
||||
|
||||
@@ -32,5 +32,6 @@ class Settings(BaseSettings):
|
||||
|
||||
class Config:
|
||||
env_file = ".env"
|
||||
extra = "ignore"
|
||||
|
||||
settings = Settings()
|
||||
|
||||
@@ -1,77 +1,90 @@
|
||||
from datetime import datetime, timedelta
|
||||
from typing import Optional, Union, Any
|
||||
|
||||
from jose import jwt
|
||||
from passlib.context import CryptContext
|
||||
from app.core.config import settings
|
||||
|
||||
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
|
||||
|
||||
def create_access_token(subject: Union[str, Any], expires_delta: Optional[timedelta] = None) -> str:
|
||||
|
||||
def create_access_token(
|
||||
subject: Union[str, Any], expires_delta: Optional[timedelta] = None
|
||||
) -> str:
|
||||
"""
|
||||
创建 JWT Access Token
|
||||
|
||||
|
||||
Args:
|
||||
subject: 用户标识(通常是用户名或用户ID)
|
||||
expires_delta: 过期时间增量
|
||||
|
||||
|
||||
Returns:
|
||||
JWT token 字符串
|
||||
"""
|
||||
if expires_delta:
|
||||
expire = datetime.utcnow() + expires_delta
|
||||
expire = datetime.now() + expires_delta
|
||||
else:
|
||||
expire = datetime.utcnow() + timedelta(minutes=settings.ACCESS_TOKEN_EXPIRE_MINUTES)
|
||||
|
||||
expire = datetime.now() + timedelta(
|
||||
minutes=settings.ACCESS_TOKEN_EXPIRE_MINUTES
|
||||
)
|
||||
|
||||
to_encode = {
|
||||
"exp": expire,
|
||||
"sub": str(subject),
|
||||
"type": "access",
|
||||
"iat": datetime.utcnow()
|
||||
"iat": datetime.now(),
|
||||
}
|
||||
encoded_jwt = jwt.encode(to_encode, settings.SECRET_KEY, algorithm=settings.ALGORITHM)
|
||||
encoded_jwt = jwt.encode(
|
||||
to_encode, settings.SECRET_KEY, algorithm=settings.ALGORITHM
|
||||
)
|
||||
return encoded_jwt
|
||||
|
||||
|
||||
def create_refresh_token(subject: Union[str, Any]) -> str:
|
||||
"""
|
||||
创建 JWT Refresh Token(长期有效)
|
||||
|
||||
|
||||
Args:
|
||||
subject: 用户标识
|
||||
|
||||
|
||||
Returns:
|
||||
JWT refresh token 字符串
|
||||
"""
|
||||
expire = datetime.utcnow() + timedelta(days=settings.REFRESH_TOKEN_EXPIRE_DAYS)
|
||||
|
||||
expire = datetime.now() + timedelta(days=settings.REFRESH_TOKEN_EXPIRE_DAYS)
|
||||
|
||||
to_encode = {
|
||||
"exp": expire,
|
||||
"sub": str(subject),
|
||||
"type": "refresh",
|
||||
"iat": datetime.utcnow()
|
||||
"iat": datetime.now(),
|
||||
}
|
||||
encoded_jwt = jwt.encode(to_encode, settings.SECRET_KEY, algorithm=settings.ALGORITHM)
|
||||
encoded_jwt = jwt.encode(
|
||||
to_encode, settings.SECRET_KEY, algorithm=settings.ALGORITHM
|
||||
)
|
||||
return encoded_jwt
|
||||
|
||||
|
||||
def verify_password(plain_password: str, hashed_password: str) -> bool:
|
||||
"""
|
||||
验证密码
|
||||
|
||||
|
||||
Args:
|
||||
plain_password: 明文密码
|
||||
hashed_password: 密码哈希
|
||||
|
||||
|
||||
Returns:
|
||||
是否匹配
|
||||
"""
|
||||
return pwd_context.verify(plain_password, hashed_password)
|
||||
|
||||
|
||||
def get_password_hash(password: str) -> str:
|
||||
"""
|
||||
生成密码哈希
|
||||
|
||||
|
||||
Args:
|
||||
password: 明文密码
|
||||
|
||||
|
||||
Returns:
|
||||
bcrypt 哈希字符串
|
||||
"""
|
||||
|
||||
@@ -13,8 +13,8 @@ from typing import List, Dict
|
||||
from datetime import datetime, timedelta, timezone
|
||||
from influxdb_client.client.write_api import SYNCHRONOUS, ASYNCHRONOUS
|
||||
from dateutil import parser
|
||||
import get_realValue
|
||||
import get_data
|
||||
# import get_realValue
|
||||
# import get_data
|
||||
import psycopg
|
||||
import time
|
||||
import app.services.simulation as simulation
|
||||
|
||||
@@ -71,7 +71,7 @@ app.add_middleware(GZipMiddleware, minimum_size=1000)
|
||||
|
||||
# 添加审计中间件(可选,记录关键操作)
|
||||
# 如果需要启用审计日志,取消下面的注释
|
||||
# app.add_middleware(AuditMiddleware)
|
||||
app.add_middleware(AuditMiddleware)
|
||||
|
||||
# Include Routers
|
||||
app.include_router(api_router, prefix="/api/v1")
|
||||
|
||||
Reference in New Issue
Block a user