276 lines
9.2 KiB
Python
276 lines
9.2 KiB
Python
from fastapi import APIRouter, Depends, HTTPException, status
|
||
from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
|
||
from sqlalchemy.orm import Session
|
||
from typing import List
|
||
from jose import JWTError, jwt
|
||
|
||
from app.config.settings import settings
|
||
from app.models.database import get_db
|
||
from app.models.models import User, Role
|
||
from app.schemas.user import UserCreate, UserUpdate, UserResponse, UserListResponse, Token, LoginRequest, RoleCreate, RoleResponse
|
||
from app.services.user import UserService
|
||
|
||
# 创建路由器
|
||
router = APIRouter(prefix="/users", tags=["users"])
|
||
|
||
# OAuth2密码Bearer
|
||
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/users/login")
|
||
|
||
|
||
async def get_current_active_user(db: Session = Depends(get_db), token: str = Depends(oauth2_scheme)):
|
||
"""获取当前活跃用户"""
|
||
try:
|
||
# 检查令牌是否在黑名单中
|
||
if UserService.is_token_blacklisted(token):
|
||
raise HTTPException(
|
||
status_code=status.HTTP_401_UNAUTHORIZED,
|
||
detail="Could not validate credentials",
|
||
headers={"WWW-Authenticate": "Bearer"},
|
||
)
|
||
|
||
# 解码令牌
|
||
payload = jwt.decode(token, settings.SECRET_KEY, algorithms=[settings.ALGORITHM])
|
||
username: str = payload.get("sub")
|
||
if username is None:
|
||
raise HTTPException(
|
||
status_code=status.HTTP_401_UNAUTHORIZED,
|
||
detail="Could not validate credentials",
|
||
headers={"WWW-Authenticate": "Bearer"},
|
||
)
|
||
|
||
# 使用UserService获取用户信息,避免直接使用User模型
|
||
user = UserService.get_user_by_username(db, username)
|
||
if not user:
|
||
raise HTTPException(
|
||
status_code=status.HTTP_401_UNAUTHORIZED,
|
||
detail="Could not validate credentials",
|
||
headers={"WWW-Authenticate": "Bearer"},
|
||
)
|
||
|
||
# 检查用户是否活跃
|
||
if user.status != "active":
|
||
raise HTTPException(status_code=400, detail="Inactive user")
|
||
|
||
# 使用UserService获取角色信息
|
||
role = UserService.get_role_by_id(db, user.role_id)
|
||
|
||
# 构建角色响应
|
||
role_response = None
|
||
if role:
|
||
role_response = RoleResponse(
|
||
id=role.id,
|
||
name=role.name,
|
||
description=role.description,
|
||
created_at=role.created_at,
|
||
updated_at=role.updated_at
|
||
)
|
||
|
||
# 构建用户响应
|
||
user_response = UserResponse(
|
||
id=user.id,
|
||
username=user.username,
|
||
email=user.email,
|
||
role_id=user.role_id,
|
||
status=user.status,
|
||
created_at=user.created_at,
|
||
updated_at=user.updated_at,
|
||
role=role_response,
|
||
role_name=role.name if role else None
|
||
)
|
||
|
||
return user_response
|
||
except JWTError:
|
||
raise HTTPException(
|
||
status_code=status.HTTP_401_UNAUTHORIZED,
|
||
detail="Could not validate credentials",
|
||
headers={"WWW-Authenticate": "Bearer"},
|
||
)
|
||
|
||
|
||
from app.schemas.user import LoginRequest
|
||
|
||
@router.post("/login", response_model=Token)
|
||
async def login(login_request: LoginRequest, db: Session = Depends(get_db)):
|
||
"""用户登录"""
|
||
user = UserService.authenticate_user(db, login_request.username, login_request.password)
|
||
if not user:
|
||
raise HTTPException(
|
||
status_code=status.HTTP_401_UNAUTHORIZED,
|
||
detail="Incorrect username or password",
|
||
headers={"WWW-Authenticate": "Bearer"},
|
||
)
|
||
|
||
# 创建访问令牌
|
||
access_token = UserService.create_access_token(
|
||
data={"sub": user.username, "user_id": user.id}
|
||
)
|
||
|
||
return {"access_token": access_token, "token_type": "bearer"}
|
||
|
||
|
||
@router.post("/register", response_model=UserResponse)
|
||
async def register(user: UserCreate, db: Session = Depends(get_db)):
|
||
"""用户注册"""
|
||
# 检查用户名是否已存在
|
||
if UserService.get_user_by_username(db, user.username):
|
||
raise HTTPException(status_code=400, detail="Username already registered")
|
||
|
||
# 检查邮箱是否已存在
|
||
if UserService.get_user_by_email(db, user.email):
|
||
raise HTTPException(status_code=400, detail="Email already registered")
|
||
|
||
# 检查角色是否存在
|
||
if not UserService.get_role_by_id(db, user.role_id):
|
||
raise HTTPException(status_code=400, detail="Role not found")
|
||
|
||
# 创建用户
|
||
db_user = UserService.create_user(db, user)
|
||
|
||
return db_user
|
||
|
||
|
||
@router.get("/me", response_model=UserResponse)
|
||
async def read_users_me(current_user: UserResponse = Depends(get_current_active_user)):
|
||
"""获取当前用户信息"""
|
||
return current_user
|
||
|
||
|
||
@router.get("/", response_model=UserListResponse)
|
||
async def get_users(
|
||
skip: int = 0,
|
||
limit: int = 100,
|
||
current_user: UserResponse = Depends(get_current_active_user),
|
||
db: Session = Depends(get_db)
|
||
):
|
||
"""获取用户列表"""
|
||
# 只有管理员可以查看用户列表
|
||
if current_user.role_name != "admin":
|
||
raise HTTPException(status_code=403, detail="Not enough permissions")
|
||
|
||
users = UserService.get_users(db, skip=skip, limit=limit)
|
||
return {"users": users, "total": len(users)}
|
||
|
||
|
||
@router.get("/{user_id}", response_model=UserResponse)
|
||
async def get_user(
|
||
user_id: str,
|
||
current_user: UserResponse = Depends(get_current_active_user),
|
||
db: Session = Depends(get_db)
|
||
):
|
||
"""获取用户信息"""
|
||
# 只有管理员或用户本人可以查看用户信息
|
||
if current_user.role_name != "admin" and current_user.id != user_id:
|
||
raise HTTPException(status_code=403, detail="Not enough permissions")
|
||
|
||
user = UserService.get_user_by_id(db, user_id)
|
||
if not user:
|
||
raise HTTPException(status_code=404, detail="User not found")
|
||
|
||
return user
|
||
|
||
|
||
@router.put("/{user_id}", response_model=UserResponse)
|
||
async def update_user(
|
||
user_id: str,
|
||
user_update: UserUpdate,
|
||
current_user: UserResponse = Depends(get_current_active_user),
|
||
db: Session = Depends(get_db)
|
||
):
|
||
"""更新用户信息"""
|
||
# 只有管理员或用户本人可以更新用户信息
|
||
if current_user.role_name != "admin" and current_user.id != user_id:
|
||
raise HTTPException(status_code=403, detail="Not enough permissions")
|
||
|
||
# 非管理员只能更新自己的信息,不能更新角色
|
||
if current_user.role_name != "admin" and "role_id" in user_update.dict():
|
||
raise HTTPException(status_code=403, detail="Cannot update role")
|
||
|
||
# 检查角色是否存在
|
||
if "role_id" in user_update.dict():
|
||
if not UserService.get_role_by_id(db, user_update.role_id):
|
||
raise HTTPException(status_code=400, detail="Role not found")
|
||
|
||
user = UserService.update_user(db, user_id, user_update)
|
||
if not user:
|
||
raise HTTPException(status_code=404, detail="User not found")
|
||
|
||
return user
|
||
|
||
|
||
@router.delete("/{user_id}")
|
||
async def delete_user(
|
||
user_id: str,
|
||
current_user: UserResponse = Depends(get_current_active_user),
|
||
db: Session = Depends(get_db)
|
||
):
|
||
"""删除用户"""
|
||
# 只有管理员可以删除用户
|
||
if current_user.role_name != "admin":
|
||
raise HTTPException(status_code=403, detail="Not enough permissions")
|
||
|
||
# 检查用户是否存在
|
||
user = UserService.get_user_by_id(db, user_id)
|
||
if not user:
|
||
raise HTTPException(status_code=404, detail="User not found")
|
||
|
||
# 删除用户
|
||
db.delete(user)
|
||
db.commit()
|
||
|
||
return {"message": "User deleted successfully"}
|
||
|
||
|
||
# 角色管理API
|
||
@router.post("/roles", response_model=RoleResponse)
|
||
async def create_role(
|
||
role: RoleCreate,
|
||
current_user: UserResponse = Depends(get_current_active_user),
|
||
db: Session = Depends(get_db)
|
||
):
|
||
"""创建角色"""
|
||
# 只有管理员可以创建角色
|
||
if current_user.role_name != "admin":
|
||
raise HTTPException(status_code=403, detail="Not enough permissions")
|
||
|
||
# 检查角色名称是否已存在
|
||
if UserService.get_role_by_name(db, role.name):
|
||
raise HTTPException(status_code=400, detail="Role name already exists")
|
||
|
||
# 创建角色
|
||
db_role = UserService.create_role(db, role)
|
||
|
||
return db_role
|
||
|
||
|
||
@router.get("/roles", response_model=List[RoleResponse])
|
||
async def get_roles(
|
||
current_user: UserResponse = Depends(get_current_active_user),
|
||
db: Session = Depends(get_db)
|
||
):
|
||
"""获取角色列表"""
|
||
# 只有管理员可以查看所有角色
|
||
if current_user.role_name != "admin":
|
||
raise HTTPException(status_code=403, detail="Not enough permissions")
|
||
|
||
roles = UserService.get_roles(db)
|
||
|
||
return roles
|
||
|
||
|
||
@router.get("/roles/{role_id}", response_model=RoleResponse)
|
||
async def get_role(
|
||
role_id: str,
|
||
current_user: UserResponse = Depends(get_current_active_user),
|
||
db: Session = Depends(get_db)
|
||
):
|
||
"""获取角色详情"""
|
||
# 只有管理员可以查看角色详情
|
||
if current_user.role_name != "admin":
|
||
raise HTTPException(status_code=403, detail="Not enough permissions")
|
||
|
||
role = UserService.get_role_by_id(db, role_id)
|
||
if not role:
|
||
raise HTTPException(status_code=404, detail="Role not found")
|
||
|
||
return role
|