286 lines
7.6 KiB
Python
286 lines
7.6 KiB
Python
"""用户管理服务 - FastAPI 应用入口模块。
|
||
|
||
提供用户注册、登录、查询、更新、删除等 RESTful API 接口。
|
||
"""
|
||
|
||
from typing import Optional
|
||
|
||
from fastapi import FastAPI, HTTPException, Query, status
|
||
from fastapi.middleware.cors import CORSMiddleware
|
||
|
||
from app.models import (
|
||
ErrorResponse,
|
||
SuccessResponse,
|
||
UserCreate,
|
||
UserLogin,
|
||
UserResponse,
|
||
UserUpdate,
|
||
)
|
||
from app.services import (
|
||
create_user,
|
||
delete_user,
|
||
get_all_users,
|
||
get_user_by_id,
|
||
get_user_count,
|
||
login,
|
||
update_user,
|
||
)
|
||
|
||
# 创建 FastAPI 应用实例
|
||
app = FastAPI(
|
||
title="User Management API",
|
||
description="用户管理服务 - 提供用户注册、登录、CRUD 等基础功能",
|
||
version="1.0.0",
|
||
)
|
||
|
||
# 添加 CORS 中间件,允许跨域访问
|
||
app.add_middleware(
|
||
CORSMiddleware,
|
||
allow_origins=["*"],
|
||
allow_credentials=True,
|
||
allow_methods=["*"],
|
||
allow_headers=["*"],
|
||
)
|
||
|
||
|
||
@app.get("/health", tags=["系统"])
|
||
async def health_check():
|
||
"""健康检查接口。
|
||
|
||
Returns:
|
||
服务运行状态信息
|
||
"""
|
||
return {
|
||
"status": "ok",
|
||
"service": "user-management-service",
|
||
"version": "1.0.0",
|
||
"total_users": get_user_count(),
|
||
}
|
||
|
||
|
||
# ──────────────────────────────────────────────
|
||
# 用户管理 API
|
||
# ──────────────────────────────────────────────
|
||
|
||
|
||
@app.post(
|
||
"/api/users",
|
||
response_model=UserResponse,
|
||
status_code=status.HTTP_201_CREATED,
|
||
tags=["用户管理"],
|
||
summary="注册新用户",
|
||
description="创建一个新的用户账户,需要提供用户名、邮箱和密码。",
|
||
responses={
|
||
201: {"description": "用户创建成功", "model": UserResponse},
|
||
400: {"description": "请求数据不合法", "model": ErrorResponse},
|
||
409: {"description": "用户名或邮箱已被占用", "model": ErrorResponse},
|
||
},
|
||
)
|
||
async def api_create_user(user_data: UserCreate):
|
||
"""用户注册接口。
|
||
|
||
Args:
|
||
user_data: 用户注册信息(用户名、邮箱、密码)
|
||
|
||
Returns:
|
||
创建成功的用户信息
|
||
|
||
Raises:
|
||
HTTPException: 当输入验证失败或用户名/邮箱已存在时抛出
|
||
"""
|
||
try:
|
||
return create_user(user_data)
|
||
except ValueError as e:
|
||
raise HTTPException(
|
||
status_code=status.HTTP_409_CONFLICT,
|
||
detail=str(e),
|
||
)
|
||
|
||
|
||
@app.get(
|
||
"/api/users",
|
||
response_model=list[UserResponse],
|
||
tags=["用户管理"],
|
||
summary="获取用户列表",
|
||
description="分页获取所有用户信息列表。",
|
||
)
|
||
async def api_get_users(
|
||
skip: int = Query(0, ge=0, description="跳过的记录数"),
|
||
limit: int = Query(10, ge=1, le=100, description="每页数量"),
|
||
):
|
||
"""获取用户列表接口。
|
||
|
||
Args:
|
||
skip: 跳过的记录数,默认 0
|
||
limit: 每页数量,默认 10,最大 100
|
||
|
||
Returns:
|
||
用户信息列表
|
||
"""
|
||
return get_all_users(skip, limit)
|
||
|
||
|
||
@app.get(
|
||
"/api/users/{user_id}",
|
||
response_model=UserResponse,
|
||
tags=["用户管理"],
|
||
summary="获取单个用户",
|
||
description="根据用户 ID 获取指定用户的详细信息。",
|
||
responses={
|
||
200: {"description": "成功获取用户信息", "model": UserResponse},
|
||
404: {"description": "用户不存在", "model": ErrorResponse},
|
||
},
|
||
)
|
||
async def api_get_user(user_id: str):
|
||
"""获取单个用户接口。
|
||
|
||
Args:
|
||
user_id: 用户 ID
|
||
|
||
Returns:
|
||
用户详细信息
|
||
|
||
Raises:
|
||
HTTPException: 当用户不存在时抛出 404
|
||
"""
|
||
user = get_user_by_id(user_id)
|
||
if user is None:
|
||
raise HTTPException(
|
||
status_code=status.HTTP_404_NOT_FOUND,
|
||
detail=f"用户 '{user_id}' 不存在",
|
||
)
|
||
return user
|
||
|
||
|
||
@app.put(
|
||
"/api/users/{user_id}",
|
||
response_model=UserResponse,
|
||
tags=["用户管理"],
|
||
summary="更新用户信息",
|
||
description="更新指定用户的用户名和/或邮箱。",
|
||
responses={
|
||
200: {"description": "更新成功", "model": UserResponse},
|
||
404: {"description": "用户不存在", "model": ErrorResponse},
|
||
409: {"description": "新用户名已被占用", "model": ErrorResponse},
|
||
},
|
||
)
|
||
async def api_update_user(user_id: str, update_data: UserUpdate):
|
||
"""更新用户信息接口。
|
||
|
||
Args:
|
||
user_id: 要更新的用户 ID
|
||
update_data: 待更新的字段
|
||
|
||
Returns:
|
||
更新后的用户信息
|
||
|
||
Raises:
|
||
HTTPException: 用户不存在抛出 404,用户名冲突抛出 409
|
||
"""
|
||
try:
|
||
result = update_user(user_id, update_data)
|
||
if result is None:
|
||
raise HTTPException(
|
||
status_code=status.HTTP_404_NOT_FOUND,
|
||
detail=f"用户 '{user_id}' 不存在",
|
||
)
|
||
return result
|
||
except ValueError as e:
|
||
raise HTTPException(
|
||
status_code=status.HTTP_409_CONFLICT,
|
||
detail=str(e),
|
||
)
|
||
|
||
|
||
@app.delete(
|
||
"/api/users/{user_id}",
|
||
response_model=SuccessResponse,
|
||
tags=["用户管理"],
|
||
summary="删除用户",
|
||
description="删除指定的用户账户。",
|
||
responses={
|
||
200: {"description": "删除成功", "model": SuccessResponse},
|
||
404: {"description": "用户不存在", "model": ErrorResponse},
|
||
},
|
||
)
|
||
async def api_delete_user(user_id: str):
|
||
"""删除用户接口。
|
||
|
||
Args:
|
||
user_id: 要删除的用户 ID
|
||
|
||
Returns:
|
||
删除成功消息
|
||
|
||
Raises:
|
||
HTTPException: 用户不存在时抛出 404
|
||
"""
|
||
success = delete_user(user_id)
|
||
if not success:
|
||
raise HTTPException(
|
||
status_code=status.HTTP_404_NOT_FOUND,
|
||
detail=f"用户 '{user_id}' 不存在",
|
||
)
|
||
return {"message": f"用户 '{user_id}' 已成功删除"}
|
||
|
||
|
||
# ──────────────────────────────────────────────
|
||
# 用户登录 API
|
||
# ──────────────────────────────────────────────
|
||
|
||
|
||
@app.post(
|
||
"/api/users/login",
|
||
response_model=UserResponse,
|
||
tags=["用户管理"],
|
||
summary="用户登录",
|
||
description="使用用户名和密码进行登录验证。",
|
||
responses={
|
||
200: {"description": "登录成功", "model": UserResponse},
|
||
401: {"description": "用户名或密码错误", "model": ErrorResponse},
|
||
},
|
||
)
|
||
async def api_login(login_data: UserLogin):
|
||
"""用户登录接口。
|
||
|
||
Args:
|
||
login_data: 登录凭证(用户名和密码)
|
||
|
||
Returns:
|
||
登录成功的用户信息
|
||
|
||
Raises:
|
||
HTTPException: 用户名或密码错误时抛出 401
|
||
"""
|
||
user = login(login_data)
|
||
if user is None:
|
||
raise HTTPException(
|
||
status_code=status.HTTP_401_UNAUTHORIZED,
|
||
detail="用户名或密码错误",
|
||
)
|
||
return user
|
||
|
||
|
||
# ──────────────────────────────────────────────
|
||
# 应用入口
|
||
# ──────────────────────────────────────────────
|
||
|
||
|
||
def main():
|
||
"""启动 FastAPI 应用的入口函数。
|
||
|
||
使用 uvicorn 运行服务,监听 0.0.0.0:8000。
|
||
"""
|
||
import uvicorn
|
||
|
||
uvicorn.run(
|
||
"app.main:app",
|
||
host="0.0.0.0",
|
||
port=8000,
|
||
reload=True,
|
||
)
|
||
|
||
|
||
if __name__ == "__main__":
|
||
main()
|